Pug Templates - How to mark option in Dropdown list as selected
Asked Answered
W

6

16

I have a Pug template that uses Bootstrap 4 as the 'layout' and receiving data from an Express/Mongoose server.

I am populating a form from MongoDB so the contents can be edited. I have been looking for ways to make a dropdown-list 'select' an option based on the value from the mongoDB document.

I have seen ways of building the dropdown-list from scratch and setting an option as 'selected', but the form is already generated and has a dropdown-list already in place. I just need to match the option with the value from the mongoDB document and set the option to display in the list.

The Pug template is as follows:

.row
  .col-sm-6
    .form-group
      label.control-label.requiredField(for='propertyType')
        | Property Type
        span.asteriskField *
      .col-xs-12
        select#propertyType.select.form-control.input-lg(form='addProperty', name='propertyType')
          option(value='0') -- Select --
          option(value='6') Home
          option(value='7') Condo
          option(value='10') Single Family Home
          option(value='11') Town House
          option(value='12') City Apartment
          option(value='13') Villa


script.
  var propertyType = document.getElementById('propertyType');

  for (var i = 0; i < propertyType.options.length; i++) {

    if (propertyType.options[i].value = #{property.typeId}) {
        propertyType.options[i].selected = 'selected';
        propertyType.selectedIndex = i;
        break;
    }

  }

If I keep the code as listed then the actual option that gets a new value is the first one '-- Select --' which has it's value changed from '0' to '6', which is the value from the MongoDB document.

If I change the javascript to pass the value #{property.TypeId} to the 'selectedIndex' like this:

propertyType.selectedIndex = #{property.typeId};

Then the value of the index changes and the 'selected' option changes - to '6' but this then selects the 6th option of the options and not the one with the value of '6'.

Drop-downs are the only thing I can't seem to populate so any help would be greatly appreciated.

Wrathful answered 12/10, 2016 at 11:34 Comment(0)
W
5

UPDATE

Hope it's ok to answer my own question. I did try Mohit's approach, but it didn't work for me.

I added a 'script.' section under each <select> input:

script.
  var pOptions = document.getElementById('propertyType').options;
  for (i=0; i < pOptions.length; i++) {
    if (pOptions[i].value == #{property.typeId}) pOptions[i].selected = true;
  }
Wrathful answered 19/10, 2016 at 18:31 Comment(1)
Yes, it's perfectly fine to answer your own question. This is a Q&A site, and every Q deserves an A!Denticle
S
25

If you just need to show an option pre-selected, then I don't think you need to use javascript for this. You can try this:

.row
  .col-sm-6
    .form-group
      label.control-label.requiredField(for='propertyType')
        | Property Type
        span.asteriskField *
      .col-xs-12
        select#propertyType.select.form-control.input-lg(form='addProperty', name='propertyType')
          option(value='0', selected= true) -- Select --
          option(value='6', selected= property.id == 6) Home
          option(value='7', selected= property.id == 7) Condo
          option(value='10', selected= property.id == 10) Single Family Home
          option(value='11', selected= property.id == 11) Town House
          option(value='12', selected= property.id == 12) City Apartment
          option(value='13', selected= property.id == 13) Villa

Assuming this dropdown shows the values corresponding to property.id, it will mark the selected attribute as true for the option whose value matches the value in property.id. Otherwise, first option will be shown selected by default.

Sikorsky answered 13/10, 2016 at 6:45 Comment(9)
But if you have 30 options (lots I know), you would have to write a lot of code. Seems it would increase updating your code base.Wrathful
@Wrathful Yes it would require a lot of code to be updated. But you can use a loop to iterate through different options and put the selected condition inside that loop. Provided that is feasible in your case.Sikorsky
I'm sorry Mohit but I see this as an inefficient solution. Especially if you then have other workflows that use different identifiers to make something applicable to be 'selected'. Say if you have a dynamic dataset that have groups that use different selectors to define the default value? You would have to add more code to define between those selectors... Thanks though.Wrathful
@Wrathful :( not sure why didn't work for you, but I use it. logic is simple, that if selected attribute is assigned true value in jade, it reflects in html as selected="selected" and that option is shown as selected. So, here one of our expressions would result true or by default the first would be shown as selected.Sikorsky
I'll give it another go ;)Wrathful
I found this was giving me 'selected=""' on the one entry that had a matching ID, and no selected tag on any of the others. This didn't work because an empty string is falsey.Jeromejeromy
@Jeromejeromy it depends on how you define the condition. In the example in this answer, the condition ` property.id == 6` should return true or false, so no string is expected. How are you specifying your condition?Sikorsky
@MohitBhardwaj I think I was actually getting something else wrong. It's still giving me 'selected=""' but it's working now. Thanks for your help.Jeromejeromy
I use modified version ``` select#content-display.form-control(name='grid_entry_source_type') each elem in [{'name': 'All', 'value': 1}, {'name': 'Pick up', 'value': 2}] option(value=elem.value, selected=(elem.value === result.grid_entry_source_type))= elem.name ```Plebeian
K
12

I used Mohit Bhardwaj's answer in a for loop for a simple solution.

select(name='image')
  option(value='' selected=!project.image) (empty)
  for img in images
    option(value=img.id selected=(img.id === project.image.id)) #{img.alt}
K answered 13/9, 2017 at 0:31 Comment(0)
W
5

UPDATE

Hope it's ok to answer my own question. I did try Mohit's approach, but it didn't work for me.

I added a 'script.' section under each <select> input:

script.
  var pOptions = document.getElementById('propertyType').options;
  for (i=0; i < pOptions.length; i++) {
    if (pOptions[i].value == #{property.typeId}) pOptions[i].selected = true;
  }
Wrathful answered 19/10, 2016 at 18:31 Comment(1)
Yes, it's perfectly fine to answer your own question. This is a Q&A site, and every Q deserves an A!Denticle
B
4

Looking at the documentation here I've found a solution that requires no javascript and works inline.

This is how I've used it in my code:

select(name="priority")
    each priority in priorities
        option(value=priority.id selected=(job.priority.id == priority.id) ) #{priority.name}
Brother answered 16/10, 2018 at 11:20 Comment(1)
Thank you for this solution it pointed me to my solution where I have a variable in template do I did simply 'option(value="xy" selected=(xy==variable)) xy' and it works like a charm!Clarissaclarisse
M
0

Here's a way to do this without requiring a script tag or unfurling the loop at all.

-var selected = true;
select(id=field.id required=required)
    each op in field.options
        option(value=op name=field.name selected=selected) #{op}
        -if(selected){
            -selected=false;
        -}

This will set the very first option in the list to "selected" utilizing the attribute setting syntax (if selected is true when evaluated selected=selected, it will append the tag).

Mccorkle answered 16/8, 2018 at 22:40 Comment(0)
P
0
              here is index.pug
              /////////////////////   

           extends layout


           block content
           h1= title
           //- p Welcome to #{title}
         style.
         input[type=text], select {
         width: 20%;
         padding: 12px 20px;
         margin: 8px 0;
         display: inline-block;
         border: 1px solid #ccc;
         border-radius: 4px;
         box-sizing: border-box;
          }
       input[type=submit] {
       width: 10%;
       background-color: #4CAF50;
       color: white;
       padding: 14px 20px;
       margin: 8px 0;
       border: none;
       border-radius: 4px;
       cursor: pointer;
        }
       input[type=submit]:hover {
       background-color: #45a049;
       }
     div {
      border-radius: 1px;
      background-color: #f2f2f2;
      padding: 20px; }
     link(rel='stylesheet', href='/scripts/css/bootstrap.css')
     script(src="/scripts/js/bootstrap.min.js")
     //-      //- 

       script(src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js")
       script(src="/jquery/jquery.js")
       h3 Choose Your Skill
       - var  optos = skills
 div
    form(action='/Skill' method="post")
 div
    label Enter- 
    input(type='text',id='zaftot',name="zaftot" ,onKeyup="myFunc(this.value)"         
    autofocus="autofocus") 
    input(type='submit',  value='Submit')  
 div   

    select(name='dropdown' id="myselect" size="4" ,onClick="myclick()",style="margin- 
    left:40px" )


    script.
          function myclick(){ 
          var t=$("#myselect").val().toString();
          $("#zaftot").val(t);
          $("#zaftot").focus();
          $("#myselect").hide();
        /// alert(t);
         };
     function memo(){ 
       /// remove  all items of list
        var x = document.getElementById("myselect");
        while(true){ 
        if (x.length > 0) {
          x.remove(x.length-1);
               }
               else{
                 break;
               }
             }
          }

     function myFunc(inp){
        $("#myselect").show();

          memo(); //clear list before initiatig new one
       if (inp.length >0){
        //alert(inp +'----hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh');
        var aa =!{JSON.stringify(optos)}
        var uu =inp.trim().toLowerCase();
         for (i = 0; i < aa.length; i++) {
          var  tt =aa[i].trim().toLowerCase();
          //var y =tt.substr(0,uu.length);
          //alert(uu);
          //if(tt.substr(0,uu.length))===uu {  // substr() not working i dont know
            if(tt.indexOf(uu)>-1){ 
              $('#myselect').append('<option>' + aa[i] + '</option>');
            };
         };
     };
    };
     ////////////////////////////////////////////////////

          here is  routes /index.js  
          /////////////////////////////

        /*esversion=6 */
        var express = require('express');
        var router = express.Router();

       router.get("/", function (req, res) {
        var  skills =["MVC", "C#", "mmm","mlll","moo","muuu" 
        ,"mdd","mkkkk","Node  
        JS", 
       "mkyy" ,  "Python" ,  "IDE visual studio","Mssql"];
        res.render('index', {
          title : "Select technology",
         skills:skills
        });
       });

     router.post("/Skill" , function(req, res){
     console.log(req.body);
     res.render('Skill',{
     skill: req.body.dropdown
     });
     });

    module.exports = router;
        //////////////////////////////////////
           package json
          {
         "name": "aziz",
            "version": "0.0.0",
            "private": true,
          "scripts": {
           "start": "nodemon ./bin/www"
         },
         "dependencies": {
         "bootstrap": "^4.1.3",
         "cookie-parser": "~1.4.3",
         "debug": "~2.6.9",
        "eslint": "^5.5.0",
         "express": "~4.16.0",
         "http-errors": "~1.6.2",
        "jquery": "^3.3.1",
        "morgan": "~1.9.0",
        "nodemon": "^1.18.4",
         "popper.js": "^1.14.3",
         "pug": "2.0.0-beta11"
        },
      "author": "azizsallam",
       "license": "ISC"
        }     
        ///////////////////////////
         add these two line to app.js

 ////////////ADD TO APP.JS the next line how to call bootstrap files in yuor          
            ///////////////////  the next line how to call bootstrap files 
 in yuor view ///////////////////
 app.use('/scripts', express.static(__dirname + 
 '/node_modules/bootstrap/dist/'));
 app.use('/jquery', express.static(__dirname + 
 '/node_modules/jquery/dist/'));
   //////////////////////////////////
Peta answered 15/9, 2018 at 6:18 Comment(5)
WORKING EXAMPLE WITH NODE and EXPRESS and pug template engine modified from another post on stack over flow that --POSTED 19TH MAY 2018 CHEN V chen.about-powershell.com/2018/05/…Peta
This is very broadJarvis
Please add explanation to your answerStash
use express generator to build your app folder and initiate json package ,Peta
MR Saeed ---I JUST ADDED PACKAGE.JSON tooPeta

© 2022 - 2024 — McMap. All rights reserved.