【问题标题】:JQuery UI Multiselect with Knockout JS - data-binding with a helper pluginJQuery UI Multiselect with Knockout JS - 使用辅助插件进行数据绑定
【发布时间】:2016-02-26 10:53:43
【问题描述】:

我正在尝试使用 KnockoutJS 绑定来实现 jQuery UI Multiselect。我想它不能在本地完成,这就是this plugin 的原因。

我正在使用插件。我在 php 代码中创建了我的多选,但输出 html 是这样的:

<select id="multiselectpoc" data-bind="multiselect  : { config : multiSelectConfig,
            options: _categories,
            optionsText: '_name',
            optionsValue: '_id',
            value: selectedCategory,
            optionsCaption: 'CATEGORY'}" title="Basic example" multiple="multiple" name="example-basic" size="5" style="display: none;">
        </select>

我知道在 php 中创建它不是问题,因为我在 php 中创建了其他不是 jqueryUI 多选的&lt;select&gt;,并且它们的数据绑定有效。

这是我的视图模型(我使用打字稿):

class SearchFilterViewModel {
    multiSelectConfig = {};
    _countriesList = [];
    _regionsList = [];
    _countries = ko.observableArray();
    _regions = ko.observableArray();
    _categories = ko.observableArray([
        new Category(name="Meat-Free Meat", 1),
        new Category(name="Dairy-Free Dairy", 2),
        new Category(name="Confectionery", 3),
        new Category(name="Baking", 4),
        new Category(name="Dessert", 5)
    ]);
    selectedCountry = ko.observable();
    selectedCity:  KnockoutObservable<string> = ko.observable('');
    selectedCategory:  KnockoutObservable<string> = ko.observable('');

    constructor(allCountries) {
        for (var index = 0; index < allCountries.length; index++) {
            this._countriesList.push(allCountries[index]);
        }
        this._countries(this._countriesList);
        this.selectedCountry.subscribe(this.updateCities.bind(this))
    }

    updateCities(geonameId) {
        var self = this;
        self._regionsList = [];
        $.ajax({
            url: `http://api.geonames.org/children?geonameId=${geonameId}&username=elion`
        }).then(function(allCitiesXML) {
            var allCitiesJSON = xml2json(allCitiesXML);
            var allCities = JSON.parse(allCitiesJSON);
            for (var index = 1; index < allCities.geonames.length - 1; index++) {
                self._regionsList.push(allCities.geonames[index].geoname);
            }
            self._regions(self._regionsList);
            });
    }
}

class Category {
    _name:  KnockoutObservable<string>;
    _id:    KnockoutObservable<number>;

    constructor(name, id) {
        this._name = ko.observable(name);
        this._id = ko.observable(id);
    }
}



$(document).ready(function() {
    var _searchFilterViewModel: SearchFilterViewModel = new SearchFilterViewModel(allCountries);
    var _searchFilterForm = $("#find-vegan-products-page").find("form")[0];
    ko.applyBindings(_searchFilterViewModel, _searchFilterForm);
    $('.select-multiple').each(function(i, obj) {
        //obj[i] gets each element inside the div
        $(this).multiselect();
    })
});

这个问题主要是关于如何在viewmodel中配置空的multiSelectConfig对象。当我在 Web 浏览器中运行该页面时,&lt;select&gt; 中的输出 html 现在是许多 &lt;li&gt; 标记,其中包含相当多的 jquery ui 多选代码,但重要的是每个 &lt;option&gt;&lt;/option&gt; 内部都是 @ 987654330@ 位于每个 &lt;li&gt; 标记内。 &lt;li&gt; 标签的数量与类别相同,这让我认为数据绑定正在工作。我只需要点击 [object object] 来获取属性(category.name)。我该怎么做?

【问题讨论】:

    标签: knockout.js jquery-ui-multiselect


    【解决方案1】:

    您可能应该浏览 KnockoutJS 教程。 AFAICT,您目前并没有真正使用它。

    绑定处理程序负责在您的 DOM 上调用 multiselect(...)。你不应该像现在这样自己称呼它。相反,您需要一个将所有信息传递给自定义绑定处理程序的视图模型。

    绑定处理程序需要config 作为输入,而您的视图告诉它您的视图模型有一个包含该信息的multiSelectConfig 属性。绑定处理程序可能会崩溃,因为您的视图模型缺少该属性。

    换句话说,您拥有的绑定处理程序假定您的视图模型具有名为的可观察对象(或至少是属性):

    • multiSelectConfig
    • _categories 分别带有 _name 和 _id 属性
    • selectedCategory

    您还没有展示您的视图模型代码或 KO 引导代码,但您需要它来让事情运行起来。例如:

    $(function(){
        var vm = {
            multiSelectConfig: { /* config here */ },
            _categories: [{_id: 1, _name: "test"},
            selectedCategory: ko.observable()
        };
        ko.applyBindings(vm);
    });
    

    这段代码浏览了很多重要的概念,例如视图模型、可观察数组、将 json 映射到视图模型等的构造函数,所以我再次建议您查看 KO 网站及其教程。

    【讨论】:

    • 谢谢。很好的资料。刚刚将我的视图模型添加到问题中。我目前正在考虑如何将 multiSelectConfig 添加到我的视图模型中。如果它是一个 ko.observable 或只是一个对象。
    • 它可以是一个静态对象:自定义绑定处理程序中的init 在开始时只会读取一次,并且不会观察到配置的任何更改。因此,SearchFilterViewModel 上的公共财产就可以解决问题。从this.multiSelectConfig = {} 或类似名称开始,您将很快启动并运行。
    • 谢谢。我所做的只是将名为multiSelectConfig 的空对象添加到视图模型中。该视图现在显示每个选项的 [object object](比以前好多了)。我的问题中的 html 输出是否正确?我是否应该在视图模型中向multiSelectConfig 添加一些代码?
    【解决方案2】:

    由于我的 css,这是使用引导程序设置样式的,这不需要它并且没有任何依赖项。

    <div class="input-group-lg input-group-xl">
         <select class="form-control needsclick" data-bind="options: ovariesJSON, selectedOptions: RightOvaryIDs, optionsText: 'Name', optionsValue: 'ID', optionsCaption: 'Select'" multiple="true"></select>
    </div>
    

    参考:http://knockoutjs.com/documentation/selectedOptions-binding.html

    他们的例子:

    <p>
        Choose some countries you'd like to visit: 
        <select data-bind="options: availableCountries, selectedOptions: chosenCountries" size="5" multiple="true"></select>
    </p>
    
    <script type="text/javascript">
        var viewModel = {
            availableCountries : ko.observableArray(['France', 'Germany', 'Spain']),
            chosenCountries : ko.observableArray(['Germany']) // Initially, only Germany is selected
        };
    
        // ... then later ...
        viewModel.chosenCountries.push('France'); // Now France is selected too
    </script>
    

    【讨论】:

    • 谢谢。不幸的是我需要选择元素有一个固定的高度(然后下拉选项),所以标准的 html 选择不起作用。
    猜你喜欢
    • 2015-03-25
    • 1970-01-01
    • 2016-12-09
    • 2015-01-19
    • 2012-04-08
    • 2015-01-01
    • 2015-12-28
    • 1970-01-01
    相关资源
    最近更新 更多