具有两组不同属性的车把。帮手还是偏心?

handlebars with two different sets of properties. helper or partial?

我有一个 json 对象,我们用 Teams 称它为 teamData。

我希望能够将 Primary 或 Secondary 等变量传递给调用,并让它呈现一个状态下拉列表,其中选择了 TeamType 的状态。

我一直在阅读许多车把教程,但其中 none 确实处理一个对象的多个 属性 或展示如何 link 从一个 属性 给另一个。

状态下拉菜单很简单

 <script type="text/x-handlebars-template" id="tmpl-states">
      <select>
           {{#eachProperty States}}
                <option name="{{property}}">{{value}}</option>
           {{/eachProperty}}
      </select>
 </script>

 Handlebars.registerHelper('eachProperty', function (context, options) {
     var ret = "";
     for (var prop in context) {
          ret = ret + options.fn({ property: prop, value: context[prop] });
     }
     return ret;
 });

但我想做的更像是(在 sudo 中)

 renderTemplate("tmps-all", "container", "data", "variable");

 <script type="text/x-handlebars-template" id="tmps-all">
      {{#each Teams}}
           {{#if TeamType == variable}} // e.g. Primary
                var State = this.State;
           {{/if}}
      {{/each}}
      <select>
           {{#eachProperty States}}
                {{#if property == State}} // e.g NY
                <option name="{{property}}" selected>{{value}}</option>
                {{/else}}
                <option name="{{property}}">{{value}}</option>
                {{/if}}
           {{/eachProperty}}
      </select>
 </script>

var teamData = {"Teams":[{"TeamType":"Primary","State":"NY"},{"TeamType":"Secondary","State":"CA"}],"States":{"AK":"Alaska","AL":"Alabama","AR":"Arkansas","AZ":"Arizona","CA":"California","CO":"Colorado","CT":"Connecticut","DC":"District of Columbia","DE":"Delaware","FL":"Florida","GA":"Georgia","HI":"Hawaii","IA":"Iowa","ID":"Idaho","IL":"Illinois","IN":"Indiana","KS":"Kansas","KY":"Kentucky","LA":"Louisiana","MA":"Massachusetts","MD":"Maryland","ME":"Maine","MI":"Michigan","MN":"Minnesota","MO":"Missouri","MS":"Mississippi","MT":"Montana","NC":"North Carolina","ND":"North Dakota","NE":"Nebraska","NH":"New Hampshire","NJ":"New Jersey","NM":"New Mexico","NV":"Nevada","NY":"New York","OH":"Ohio","OK":"Oklahoma","OR":"Oregon","PA":"Pennsylvania","PR":"Puerto Rico","RI":"Rhode Island","SC":"South Carolina","SD":"South Dakota","TN":"Tennessee","TX":"Texas","UT":"Utah","VA":"Virginia","VT":"Vermont","WA":"Washington","WI":"Wisconsin","WV":"West Virginia","WY":"Wyoming"}};

不需要您的 eachProperty 帮手。它为您提供的功能已经存在于 Handlebars 中。让我们删除该助手并将我们的模板更新为以下内容(注意:我将用 value 替换 name 属性):

<select>
    {{#each States}}
        <option value="{{@key}}">{{this}}</option>
    {{/each}}
</select>

现在开始设置 selected 属性的任务。

您在模板中尝试了过多的逻辑。不是为模板初始化变量。这项工作应该在 呈现模板之前 完成。我们希望我们的代码调用模板方法来为模板提供它需要的所有数据。这意味着将像这样的数据结构传递给我们的模板:

[
    {
        value: 'AK',
        label: 'Alaska',
        selected: false
    },
    {
        value: 'AL',
        label: 'Alabama',
        selected: false
    },
    // and so on...
]

我们的代码将完成构建此数据结构的工作:

var selected_team = teamData.Teams.find(team => team.TeamType === 'Primary');
var states = Object.keys(teamData.States).map(key => ({
    value: key,
    label: teamData.States[key],
    selected: (key === selected_team.State)
}));

现在我们可以修改我们的模板来处理我们的新数据结构:

<select>
    {{#each this}}
        <option value="{{value}}" {{#if selected}}selected{{/if}}>{{label}}</option>
    {{/each}}
</select>

当我们调用我们的模板时,我们只需传入我们的 states 变量:

renderTemplate(states);

但是: 在我们完成所有这些工作后,我想补充一点,我认为重新呈现此模板只是为了反映已更改的所选选项没有任何意义。使用 DOM 进行更改对我来说更有意义。像下面这样的东西就足够了:

document.querySelector('#Select [value="NY"]').selected = true;

参见: