如何在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>