简体   繁体   English

用敲除js绑定html嵌套的select语句

[英]Binding html nested select statements with knockout js

There is a page with nested HTML select statements. 有一个带有嵌套HTML select语句的页面。 Examples of how to bind selects in KnockoutJS assume the option values are in the view model. 在KnockoutJS中如何绑定选择的示例假定选项值在视图模型中。 Here the options exist as HTML. 这里的选项以HTML格式存在。

What syntax/functions would be used to bind the second select to the class name of the first select options so that they only appear in the second list when the corresponding class is selected? 什么语法/功能将用于将第二个选择绑定到第一个选择选项的类名,以便仅在选择相应的类时才将它们显示在第二个列表中? In other words, what would replace the space holder "whenStartAppGroupNSelected." 换句话说,将替换空格符“ whenStartAppGroupNSelected”。

Markup : 标记:

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

Model : 型号:

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

I think what you have here is generally against the grain when it comes to knockout.js. 我认为,在敲除ockout.js时,您通常所遇到的困难。 Your view model(s) should be constructed in such a way that they provide an accurate representation of your data. 您的视图模型的构建方式应能提供数据的准确表示。

Instead, I would create a separate StartOption view model object to act as the "values" of the two drop-downs. 相反,我将创建一个单独的StartOption视图模型对象,以充当两个下拉列表的“值”。 Each StartOption would have an observable array for the sub-options, and then your main view model would have a list of StartOption s for the first-level objects, and each of those would have a list of the level-two items. 每个StartOption都有一个用于子选项的可观察数组,然后您的主视图模型将具有一个用于第一级对象的StartOption列表,并且每个对象都将具有一个第二级项目列表。

Something like this: 像这样:

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

And then the JS: 然后是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 以上工作演示

Or perhaps you want to load the options from the server via AJAX, and your JSON response looks like: 或者,也许您想通过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' }
         ]
     }
];

You could use the knockout-mapping plug-in to do some of the heavy lifting for you so you can simplify your view models: 您可以使用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 以上工作演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM