如何在Handlebars模板中设置选定的选项

有了像这样的Handlebars.js模板…

<select> <option value="Completed">Completed</option> <option value="OverDue">OverDue</option> <option value="SentToPayer">SentToPayer</option> <option value="None">None</option> </select> 

…和这样的数据…

 { "id" : 1, "name" : "World" "status" : "OverDue", "date" : "2012-12-21" } 

我想要这样呈现HTML。

 <select> <option value="Completed">Completed</option> <option value="OverDue" selected="selected">OverDue</option> <option value="SentToPayer">SentToPayer</option> <option value="None">None</option> </select> 

哪种方法最简单?

我发现很多复杂的解决scheme,并决定使用Handlebars助手编写我自己的解决scheme。

有了这个部分(使用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(); }); 

您可以用您的Handlebars模板将select换成{{#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> 

并最终与此…

 <select> <option value="Completed">Completed</option> <option value="OverDue" selected="selected">OverDue</option> <option value="SentToPayer">SentToPayer</option> <option value="None">None</option> </select> 

普雷斯托!

我只是和OP有类似的需求 – 有一组静态的select选项,但是是一个dynamicselect的值。 我真的很喜欢@ janjarfalk的解决scheme,但是我使用的是node.js,并没有将jQuery引入。所以,我将基于RegExp的变体放在一起。 希望这对别人有帮助。

把手帮手:

 hbs.registerHelper('select', function(selected, options) { return options.fn(this).replace( new RegExp(' value=\"' + selected + '\"'), '$& selected="selected"'); }); 

把手模板:

 <select> {{#select CurrentSort}} <option value="1">Most Recent First</option> <option value="2">Most Recent Last</option> <option value="3">Highest Score First</option> <option value="4">Highest Score Last</option> <option value="5">Most Comments</option> <option value="6">Fewest Comments</option> <option value="7">Most Helpful Votes</option> <option value="8">Fewest Helpful Votes</option> {{/select}} </select> 

即使不使用value属性,也可以调整助手的工作方式 – 只需调整正则expression式来search元素文本,然后在匹配的文本之前进行stringreplace。

我看到@janjarfalk发布的非常聪明的解决scheme,并意识到它不适用于没有值属性定义的选项(如<option>Value</option> )。 我的应用程序需要,我想要一个帮助完成在香草JavaScript的性能,所以我想出了以下内容。

除了<option value="aValue">A label</option>之外,此解决scheme将支持<option>Both a label and a value</option> ,并且会更快,因为它不使用jQuery。

 Handlebars.registerHelper('select', function(value, options) { // Create a select element var select = document.createElement('select'); // Populate it with the option HTML select.innerHTML = options.fn(this); // Set the value select.value = value; // Find the selected node, if it exists, add the selected attribute to it if (select.children[select.selectedIndex]) select.children[select.selectedIndex].setAttribute('selected', 'selected'); return select.innerHTML; }); 

用法:

 <select> {{#select status}} <option>Option 1</option> <option>Option 2</option> <option value="Option 3">Option 3 (extra info)</option> <option value="Option 4">Option 4 (more extra)</option> {{/select}} </select> 

由于上下文的原因,使用“每个”助手构builddynamic的东西时,我遇到了“select块”方法的问题。

这是我的解决scheme:

  Handlebars.registerHelper('option', function(value, label, selectedValue) { var selectedProperty = value == selectedValue ? 'selected="selected"' : ''; return new Handlebars.SafeString('<option value="' + value + '"' + selectedProperty + '>' + label + "</option>"); }); 

和模板:

 <select> {{#each status}} {{option id name ../statusId}} {{/each}} </select> 

改进了@lazd的回答,当没有任何匹配时select第一个选项。

 Handlebars.registerHelper('select', function(value, options) { // Create a select element var select = document.createElement('select'); // Populate it with the option HTML $(select).html(options.fn(this)); //below statement doesn't work in IE9 so used the above one //select.innerHTML = options.fn(this); // Set the value select.value = value; // Find the selected node, if it exists, add the selected attribute to it if (select.children[select.selectedIndex]) { select.children[select.selectedIndex].setAttribute('selected', 'selected'); } else { //select first option if that exists if (select.children[0]) { select.children[0].setAttribute('selected', 'selected'); } } return select.innerHTML; }); 

用法保持不变:

 <select> {{#select status}} <option>Option 1</option> <option>Option 2</option> <option value="Option 3">Option 3 (extra info)</option> <option value="Option 4">Option 4 (more extra)</option> {{/select}} </select> 

我刚刚遇到这个问题,这是一个解决scheme,当选项是dynamic的..

我创build了一个选项助手来接受您希望select的项目的值,而不是创build一个select助手。

 Handlebars.registerHelper('option', function(value) { var selected = value.toLowerCase() === (this.toString()).toLowerCase() ? 'selected="selected"' : ''; return '<option value="' + this + '" ' + selected + '>' + this + '</option>'; }); 

并在我的模板。

 {{#items}} {{{option ../selected_value}}} {{/items}} 

请注意../来访问父级的范围,因为它不可能在selected_value将在items数组中。

干杯。

我更喜欢使用模板方法。 通过这个我的意思是select标签本身的布局是在handlebars模板(有人可能会查找它),而不是在JavaScript帮助器中指定。 块帮助程序中的模板被传递到帮助程序脚本中,可以通过调用options.fn()来使用,然后使用您在帮助程序中所做的任何脚本更改。

模板:

 <select> {{#optionsList aStatusList sCurrentStatusCode 'statusCode'}} <option {{isSelected}} value="{{statusCode}}">{{statusName}}</option> {{/optionsList}} </select> 

稍微修改的数据(不是必需的,但对我来说更“真实的世界”)

 var myOrder = { "id" : 1, "name" : "World", "statusName" : "OverDue", /* status should NOT be here! */ "statusCode" : "1", "date" : "2012-12-21" } var sCurrentStatusCode = myOrder.statusCode; var aStatusList = [ { "statusName" : "Node", "statusCode" : 0 }, { "statusName" : "Overdue", "statusCode" : 1 }, { "statusName" : "Completed", "statusCode" : 2 }, { "statusName" : "Sent to Payer", "statusCode" : 3 } ] 

Javascript注册助手:

 Handlebars.registerHelper( 'optionsList', function ( aOptions, sSelectedOptionValue, sOptionProperty, options ) { var out = ""; for ( var i = 0, l = aOptions.length; i < l; i++ ) { aOptions[ i ].isSelected = ''; if( ( sOptionProperty != null && sSelectedOptionValue == aOptions[ i ][ sOptionProperty ] ) || ( sSelectedOptionValue == aOptions[ i ] ) ) { aOptions[ i ].isSelected = ' selected="selected" '; } out = out + options.fn( aOptions[ i ] ); } return out; } ); 

optionsList是我select这个帮手的名字

aStatusList状态对象数组包含多个属性,包括状态值/名称(在大多数情况下,我遇到过这种状态代码,而不是存储的状态名称)

sCurrentStatus是之前select的状态码(不是值),是我希望在生成的选项列表中select的选项值。

statusCode是aStatusList对象内的string属性名称,我将testing它是否匹配myStatus,它是aStutusList [loopIndex] [ statusCode ]

  • string选项属性(本例中为statusCode)只是对象需要的 – 选项列表也可以是string数组(而不是包含string的对象),在这种情况下,可以省略第三个属性“statusCode”,它告诉助手什么属性的对象再次testing。 如果你不通过该属性,它只会testing列表项本身。
  • 如果sSelectedOptionValue没有通过,那么列表将被生成而不设置任何项目来select。 这将产生与使用{{#each}}帮助程序几乎相同的列表

如果你有很less的select,你不想写一个帮手,这是你可以做的:

 //app.js var data = {selectedVal: 'b'}; // can also use switch ... case ... if (data.selectedVal === 'a') { data.optionASelected = true; } else if (data.selectedVal === 'b') { data.optionBSelected = true; } // assuming you have a template function to handle this data templateFunc(data); 

在您的模板文件中:

 <!-- template.html --> <select id="select-wo-helper" > <option value="a" {{#if optionASelected}} selected {{/if}}>A</option> <option value="b" {{#if optionBSelected}} selected {{/if}}>B</option> </select> 

再次,这可能不是所有的最好的解决scheme,但它可能是一个非常快速的工作,当你处理很less的select,并希望快速解决。

应该提到的是,如果你不关心重复…你可以使用香草把手,并首先放置select的选项,如:

  <select name="ingredient"> <option value="{{ingredient.id}}" selected>{{ingredient.name}}</option> {{#each ingredients}} <option value="{{this.id}}">{{this.name}}</option> {{/each}} </select> 

@ lazd的答案不适用于<optgroup> <option>元素。

对于所有的<option> s, selectedIndex是单调编号的,但select.children包含<optgroup> s,而select.children[n].children <optgroup><optgroup> n中包含<option> s(编号在每个<optgroup> ,当然)。

这个替代版本可以用于<optgroup><option>元素:

 Handlebars.registerHelper('select-optgrp', function(value, options) { var select = document.createElement('select'); // create a select element select.innerHTML = options.fn(this); // populate it with the option HTML select.value = value; // set the value var g = 0, i = select.selectedIndex; // calculate which index of which optgroup while (i >= select.children[g].children.length) { i -= select.children[g].children.length; g++; } if (select.children[g].children[i]) { // if selected node exists add 'selected' attribute select.children[g].children[i].setAttribute('selected', true); } return select.innerHTML; }); 

为我工作

 <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> 

这可能需要更多的代码在模板中,但它更容易阅读:

.js文件

 Handlebars.registerHelper('select', function(selected, option) { return (selected == option) ? 'selected="selected"' : ''; }); 

.hbs

 <select name="status"> <option value="public" {{{select story.status 'public'}}}>Public</option> <option value="private" {{{select story.status 'private'}}}>Private</option> <option value="unpublished" {{{select story.status 'unpublished'}}}>Unpublished</option> </select> 

另一个使用express-handlebars和dynamic选项的解决scheme是这样的。

助手function(从所有选项中select一个我们想要的,并将其更改为选定)。

 select: function(selected, options) { return options.fn(this) .replace( new RegExp(' value=\"' + selected + '\"'), '$& selected="selected"') .replace( new RegExp('>' + selected + '</option>'), ' selected="selected"$&'); } 

handlebars文件(我只是使用#each内select接收我的数据,像一个魅力工作)。

 <select name="justAname"> {{#select content.campusId}} {{#each campus}} <option value="{{id}}">{{name}}</option> {{/each}} {{/select}} </select>