With a Handlebars.js template like this...
I've had problems with the "select block" approach when using the "each" helper to build something dynamic, due to the context.
Here is my solution:
Handlebars.registerHelper('option', function(value, label, selectedValue) {
var selectedProperty = value == selectedValue ? 'selected="selected"' : '';
return new Handlebars.SafeString('<option value="' + value + '"' + selectedProperty + '>' + label + "</option>");
});
And the template:
<select>
{{#each status}}
{{option id name ../statusId}}
{{/each}}
</select>
It should be mentioned that if you do not care about repeats... you can just use vanilla handlebars and place the selected option first, such as:
<select name="ingredient">
<option value="{{ingredient.id}}" selected>{{ingredient.name}}</option>
{{#each ingredients}}
<option value="{{this.id}}">{{this.name}}</option>
{{/each}}
</select>
I found a lot of over complicated solutions and decided to write my own using a Handlebars helper.
With this partial (using Jquery) ...
window.Handlebars.registerHelper('select', function( value, options ){
var $el = $('<select />').html( options.fn(this) );
$el.find('[value="' + value + '"]').attr({'selected':'selected'});
return $el.html();
});
You can wrap selects in your Handlebars template with {{#select status}}...
<select>
{{#select status}}
<option value="Completed">Completed</option>
<option value="OverDue">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
{{/select}}
</select>
and end up with this...
<select>
<option value="Completed">Completed</option>
<option value="OverDue" selected="selected">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
</select>
Presto!
Data source
selectedValue: "8",
option:[
{id_sub_proyectop: "8", clave: "021", name: "Cliclismo"},
{id_sub_proyectop: "9", clave: "022", name: "Atletismo"},
],
helper
Handlebars.registerHelper('selected', function(value, prop) {
if (value === undefined){ return '';};
return value === this[prop] ? 'selected="selected"' : '';
});
Template
<div class="medium-6 cell">
<label>Sub Proyecto / Proceso:
<select name="id_sub_proyectop" required>
{{#each option}}
<option value="{{id_sub_proyectop}}" {{{selected ../selectedValue 'id_sub_proyectop'}}}>{{clave}} - {{name}}</option>
{{/each}}
</select>
</label>
</div>
Today I was also facing the same problem I'm creating a Content Management System and to fetch the status of the post I stuck and in searching for a solution, I landed on this page I found a few answers relevant Because I'm using server-side data and when I used document.createElement it is throwing error document is not defined.
The Regex solution worked for me but I want an easy to understand one whether it is verbose so I came with this solution.
Handlebars.registerHelper('getValue', function(value, options) {
if(options.fn(this).indexOf(value) >= 1){
return `selected='selected'`;
}
});
in the template use the code in this way
<select name="post-status" id="post-status">
<option {{#getValue posts.postStatus}} value="Draft" {{/getValue}} >Draft</option>
<option {{#getValue posts.postStatus}} value="private" {{/getValue}} >private</option>
<option {{#getValue posts.postStatus}} value="publish" {{/getValue}} >publish</option>
</select>
If I'm wrong somewhere Please correct me.
Works for me
<select>
<option value="{{status}}" hidden="hidden" selected="selected">{{status}}</option>
<option value="Completed">Completed</option>
<option value="OverDue">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
</select>