使用knockout js绑定html嵌套的select语句

时间:2013-12-12 00:08:02

标签: javascript html select knockout.js nested

有一个包含嵌套HTML select语句的页面。如何在KnockoutJS中绑定选择的示例假设选项值在视图模型中。这里的选项以HTML格式存在。

将使用哪些语法/函数将第二个选择绑定到第一个选择选项的类名,以便它们仅在选择相应的类时出现在第二个列表中?换句话说,什么会取代空间持有者“whenStartAppGroupNSelected。”

加价:

<div class="apps">
    <select id="startapp" name="startapp" data-bind="value: startapp">
        <option value="value1" class="groupA">Some Val 1</option>
        <option value="value2" class="groupB">Some Val 2</option>
        <option value="value3" class="groupC">Some Val 3</option>
    </select>
</div>
<div class="pages">
     <select id="startpage" name="startpage" data-bind="value: startpage">
         <option data-bind="visible: whenStartAppGroupASelected" value="path1" class="groupA">Page 1</option>
         <option data-bind="visible: whenStartAppGroupBSelected" value="path2" class="groupB">Page 2</option>
         <option data-bind="visible: whenStartAppGroupCSelected" value="path3" class="groupC">Page 3</option>
         <option data-bind="visible: whenStartAppGroupCSelected" value="path4" class="groupC">Page 4</option>
     </select>
</div>

型号:

myModel = function() {
    var self = this;
    self.startapp = ko.observable("").extend({required: true});
    self.startpage = ko.observable("");
    self.selectedApp = ko.computed(function() {
        return self.startapp();
    });
};

1 个答案:

答案 0 :(得分:2)

我认为你所拥有的东西通常是针对knockout.js的。您的视图模型的构建方式应能够准确表示您的数据。

相反,我会创建一个单独的StartOption视图模型对象来充当两个下拉列表的“值”。每个StartOption都有一个子选项的可观察数组,然后你的主视图模型将有一个StartOption列表用于第一级对象,每个对象都有一个列表二级项目。

这样的事情:

<div class="apps">
    <select id="startapp" name="startapp" 
        data-bind="options: startApps, optionsText: 'text', value: selectedStartApp, optionsCaption: 'Choose...'">
    </select>
</div>
<div class="pages" data-bind="with: selectedStartApp">
     <select id="startpage" name="startpage" 
         data-bind="options: subOptions, optionsText: 'text', value: $root.selectedStartPage">
     </select>
</div>

然后是JS:

var StartOption = function(value, text, options) {
    var self = this;
    self.value = ko.observable(value);
    self.text = ko.observable(text);
    self.subOptions = ko.observableArray(options || []);
};

var ViewModel = function() {
    var self = this; 

    self.startApps = ko.observableArray([
        new StartOption('value1', 'Some Val 1', [
            new StartOption('path1', 'Page 1')
        ]),
        new StartOption('value2', 'Some Val 2', [
            new StartOption('path2', 'Page 2')
        ]),
        new StartOption('value3', 'Some Val 3', [
            new StartOption('path3', 'Page 3'),
            new StartOption('path4', 'Page 4')
        ])
    ]);

    self.selectedStartApp = ko.observable();
    self.selectedStartPage = ko.observable();
};

ko.applyBindings(new ViewModel());

Working Demo of Above

或许你想通过AJAX从服务器加载选项,你的JSON响应如下:

var sampleData = [
    { 
        value: 'value1', 
        text: 'Some Val 1', 
        subOptions: [
            { value: 'path1', text: 'Page 1' }
        ]
    },
    { 
        value: 'value2', 
        text: 'Some Val 2', 
        subOptions: [
            { value: 'path2', text: 'Page 2' }
        ]
    },
    { 
        value: 'value3', 
        text: 'Some Val 3', 
        subOptions: [
            { value: 'path3', text: 'Page 3' },
            { value: 'path4', text: 'Page 4' }
         ]
     }
];

你可以使用knockout-mapping插件为你做一些繁重的工作,这样你就可以简化视图模型:

var StartOption = function(data) {
    var self = this;
    // map the properties of the data object as observables
    // on this object; if we encounter "subOptions", make them
    // instances of this object as well
    ko.mapping.fromJS(data || {}, {
        'subOptions': {
            create: function(options) {
                return new StartOption(options.data);   
            }
        }
    }, self);
};

var ViewModel = function() {
    var self = this; 

    self.startApps = ko.observableArray();

    self.load = function(data) {
        self.startApps(ko.utils.arrayMap(data || [], function(option) {
            return new StartOption(option);
        }));
    };

    self.selectedStartApp = ko.observable();
    self.selectedStartPage = ko.observable();
};

var viewModel = new ViewModel();
viewModel.load(sampleData); 

ko.applyBindings(viewModel);

Working Demo of Above