54

使用像这样的 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>

哪种方式最简单?

4

18 回答 18

92

我发现了很多过于复杂的解决方案,并决定使用 Handlebars 助手编写自己的解决方案。

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

您可以使用 {{#select status}}... 在您的 Handlebars 模板中包装选择...

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

快!

于 2012-10-24T09:29:29.277 回答
36

我只是有与 OP 类似的需求——使用一组静态的选择选项,但有一个动态的选择值。我真的很喜欢@janjarfalk 的解决方案,但我使用的是 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属性,您也可以调整帮助程序以使其工作——只需调整正则表达式以搜索元素文本,并在匹配的文本之前进行字符串替换。

于 2013-06-04T22:17:52.300 回答
20

我看到@janjarfalk 发布的极其聪明的解决方案,并意识到它不适用于没有值属性定义的选项(例如<option>Value</option>)。我的应用程序需要它,并且我想要一个用 vanilla JavaScript 完成的助手来提高性能,所以我想出了以下内容。

该解决方案将支持<option>Both a label and a value</option>并且<option value="aValue">A label</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>
于 2013-03-12T22:10:37.723 回答
16

为我工作

<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>
于 2017-06-19T09:27:01.877 回答
10

由于上下文的原因,在使用“每个”帮助器构建动态的东西时,我遇到了“选择块”方法的问题。

这是我的解决方案:

  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>
于 2013-12-06T14:45:15.770 回答
7

改进了@lazd 的答案,以在没有匹配项时选择第一个选项。

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>
于 2013-08-21T05:54:08.090 回答
4

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

.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>
于 2017-10-18T04:28:09.207 回答
2

我只是遇到了这个问题,这里有一个解决方案,用于何时动态。

我没有创建选择助手,而是创建了一个选项助手,它接受您希望选择的项目的值。

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 数组内。

干杯。

于 2013-04-25T06:39:02.437 回答
2

我更喜欢使用模板方法。我的意思是选项标签本身的布局是在车把模板中指定的(有人可能会在其中查找它),而不是在 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是我选择给这个助手命名的

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

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

statusCode是 aStatusList 对象中的字符串属性名称,我将测试它是否与 myStatus 匹配,即 aStutusList[ loopIndex ][ statusCode ]

  • 字符串选项属性(在这种情况下为 statusCode )仅对对象是必需的 - 选项列表也可以是字符串数组(而不是反过来包含字符串的对象),在这种情况下,您可以省略第三个属性“statusCode”,它告诉助手要再次测试对象的什么属性。如果您不通过该属性,它只会测试列表项本身。
  • 如果 sSelectedOptionValue 未通过,则将生成列表而不将任何项目设置为选中。这将生成与使用{{#each}}帮助器几乎相同的列表
于 2015-07-16T15:48:17.490 回答
1

今天我也面临同样的问题,我正在创建一个内容管理系统并获取我卡住的帖子的状态并在寻找解决方案时,我登陆这个页面我找到了一些相关的答案因为我正在使用服务器-side 数据,当我使用 document.createElement 时,它抛出错误文档未定义。

正则表达式解决方案对我有用,但我想要一个易于理解的解决方案是否冗长,所以我提出了这个解决方案。

 Handlebars.registerHelper('getValue', function(value, options) {
   if(options.fn(this).indexOf(value) >= 1){
         return `selected='selected'`;
      }
});

在模板中以这种方式使用代码

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

如果我在某个地方错了,请纠正我。

于 2019-11-26T20:15:43.050 回答
1

如果您的选择很少并且不想编写帮助程序,那么您可以执行以下操作:

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

同样,这可能不是最好的解决方案,但当您处理的选项很少并且想要快速修复时,它可能是一个非常快速的解决方案。

于 2016-08-02T21:25:35.503 回答
1

数据源

selectedValue: "8",
option:[
    {id_sub_proyectop: "8", clave: "021", name: "Cliclismo"},
    {id_sub_proyectop: "9", clave: "022", name: "Atletismo"},
],

帮手

Handlebars.registerHelper('selected', function(value, prop) {
    if (value === undefined){ return '';};
    return value === this[prop] ? 'selected="selected"' : '';
});

模板

<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>
于 2019-12-05T23:43:41.773 回答
0

我知道这并不能直接回答问题,但是在这种情况下,我将未选择的 html 选项传递给模板,并在渲染后使用 jquery 将 json 对象指示的值标记为已选择

于 2020-05-29T20:53:57.700 回答
0

<option>@lazd的答案不适用于<optgroup>.

selectedIndex对所有<option>s 进行单调编号,但select.children保留<optgroup>s,并将 sselect.children[n].children保留<option><optgroup>n 内(当然,编号在每个 内重新开始<optgroup>)。

此替代版本适用<option>于 s 中的元素<optgroup>

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;
});
于 2016-12-09T12:22:59.457 回答
0

另一种使用express-handlebars和动态选项的解决方案是这个。

辅助函数(从所有选项中获取我们想要的选项并将其更改为选中)。

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

handlebars 文件(我只是在 select 中使用 #each 来接收我的数据并像魅力一样工作)。

<select name="justAname">
  {{#select content.campusId}}
    {{#each campus}}
      <option value="{{id}}">{{name}}</option>
    {{/each}}
  {{/select}}
</select>
于 2017-10-31T02:59:48.240 回答
0

对于数组

function select(selected, options) {
    return options.fn(this).replace( new RegExp(' value=\"' + selected + '\"'), '$& selected="selected"').replace( new RegExp('>' + selected + '</option>'), ' selected="selected"$&');
  },
于 2021-05-17T03:00:17.827 回答
0
Handlebars.registerHelper('select', function( value, options ){
  return options.fn(this)
  .replace( new RegExp(' value=\"' + value + '\"'), '$& selected="selected"')
  .replace( new RegExp('>' + value + '</option>'), ' selected="selected"$&');
});

user.country from db session
country stored in country.json file

<select id="country" name="country" class="form-control">
<option value="" selected="selected">(please select a country)</option>
{{#select user.country}}
{{#each countries as |value key| }}
<option value="{{ value.code }}">{{ value.name }}</option>
{{/each}}
{{/select}}
</select>
于 2018-05-30T06:57:53.890 回答
0

应该提到的是,如果您不关心重复......您可以使用香草车把并将所选选项放在第一位,例如:

        <select name="ingredient">
        <option value="{{ingredient.id}}" selected>{{ingredient.name}}</option>
        {{#each ingredients}}
        <option value="{{this.id}}">{{this.name}}</option>
        {{/each}}
        </select>
于 2016-11-11T19:49:30.657 回答