使用Handlebars.js,如何使用全局上下文数据填充选择框,但是使用当前循环项中的数据设置所选项?

时间:2013-08-29 11:30:35

标签: javascript json handlebars.js

给出以下JSON:

{
    "Colours": [
        { "ColourID": 1, "Name": "Red" },
        { "ColourID": 2, "Name": "Yellow" },
        { "ColourID": 3, "Name": "Blue" }
    ],
    "Sizes": [
        { "SizeID": 1, "Name": "Small" },
        { "SizeID": 2, "Name": "Medium" },
        { "SizeID": 3, "Name": "Large" }
    ],
    "Products": [
        { "ColourID": 1, "SizeID": 1, "Name": "Red Small" },
        { "ColourID": 1, "SizeID": 2, "Name": "Red Medium" },
        { "ColourID": 1, "SizeID": 3, "Name": "Red Large" },
        // and so on...
    ]
}

以下模板HTML:

<table>
    {{#Products}}
    <tr>
        <td>
            <input type="text" value="{{Name}}">
        </td>
        <td>
            <select>
                {{#Colours}}
                <option value="{{ColourID}}">{{Name}}</option>
                {{/Colours}}
            </select>
        </td>
        <td>
            <select>
                {{#Sizes}}
                <option value="{{SizeID}}">{{Name}}</option>
                {{/Sizes}}
            </select>
        </td>
    </tr>
    {{/Products}}
</table>

如何使用全局上下文中的常用颜色/大小数据构建select框,但是对于每个表行,在具有与当前产品颜色匹配的值的选项上设置selected="selected"属性/尺码ID?

就目前而言,在循环内无法访问ColoursSizes数组,因此选择为空白。我尝试使用全局帮助器在呈现之前将它们显式地从全局上下文传递到每个产品中,如下所示:

Handlebars.registerHelper('productloop', function(context, options) {
    var ret = [];

    for(var i=0, j=context.Products.length; i<j; i++) {
        var option = context.Products[i];

        option.Colours = context.Colours;
        option.Sizes = context.Sizes;

        ret.push(options.fn(option));
    }

    return ret.join('');
});

HTML:

<table>
    {{#productloop}}
    <tr>
        <td>
            <input type="text" value="{{Name}}">
        </td>
        <td>
            <select>
                {{#Colours}}
                <option value="{{ColourID}}">{{Name}}</option>
                {{/Colours}}
            </select>
        </td>
        <td>
            <select>
                {{#Sizes}}
                <option value="{{SizeID}}">{{Name}}</option>
                {{/Sizes}}
            </select>
        </td>
    </tr>
    {{/productloop}}
</table>

哪个确实有效,但看起来非常笨重,我仍然不知道如何为每个产品的颜色/尺寸选择设置selected属性。

任何人都可以帮助我吗?我可以控制生成JSON的代码,因此可以根据需要更改JSON结构。

2 个答案:

答案 0 :(得分:5)

您可以使用../在命名空间中升级一个级别:

<select>
    {{#each ../Colours}}
    <option value="{{ColourID}}">{{Name}}</option>
    {{/each}}
</select>

我也切换到{{#each}},因为我发现在处理../时更具可读性。

演示:http://jsfiddle.net/ambiguous/pFpS4/

答案 1 :(得分:1)

在当前产品的车把模板中添加所选属性。 例如。为蓝色,小,红色媒体...

{
    Colours: [
        { "ColourID": 1, "Name": "Red" },
        { "ColourID": 2, "Name": "Yellow" },
        { "ColourID": 3, "Name": "Blue", "selected" : "selected"  }
    ],
    Sizes: [
        { "SizeID": 1, "Name": "Small" , "selected" : "selected" },
        { "SizeID": 2, "Name": "Medium" },
        { "SizeID": 3, "Name": "Large" }
    ],
    Products: [
        { "ColourID": 1, "SizeID": 1, "Name": "Red Small" },
        { "ColourID": 1, "SizeID": 2, "Name": "Red Medium", "selected" : "selected" },
        { "ColourID": 1, "SizeID": 3, "Name": "Red Large" },
        // and so on...
    ]
}

然后在模板中使用它,如下所示。

<table>
    {{#Products}}
    <tr>
        <td>
            <input type="text" value="{{Name}}">
        </td>
        <td>
            <select>
                {{#Colours}}
                <option value="{{ColourID}}" {{selected}}>{{Name}}</option>
                {{/Colours}}
            </select>
        </td>
        <td>
            <select>
                {{#Sizes}}
                <option value="{{SizeID}}"  {{selected}}>{{Name}}</option>
                {{/Sizes}}
            </select>
        </td>
    </tr>
    {{/Products}}
</table>