【问题标题】:Knockout Custom Binding handler inside template模板内的淘汰赛自定义绑定处理程序
【发布时间】:2023-04-08 22:51:01
【问题描述】:

我创建了一个自定义绑定处理程序来呈现一个 html 选择组件。

EG:

 <select data-bind="dynamicSelect: { src:  'Category', label: 'Category'} "></select>

用户选择一个类别后,类别字段数组被填充,我已将其绑定到将呈现某个模板的 div

  <div data-bind="template: { name: displayMode, foreach: categoryFields }"></div>

我的模板

<script type="text/html" id="inputTemplate">
    <label data-bind="text: FieldName, attr: { for: FieldName }"></label>
    <input data-bind="attr: { name: FieldName, type: $parent.fieldType($data) }" />
</script>
<script type="text/html" id="lookupTemplate">
    <label data-bind="text: FieldName, attr: { for: FieldName }"></label>
    <select data-bind="dynamicSelect: { src: FieldName, label: FieldName}"></select>
</script>

问题是,模板内的 dynamicSelect 似乎没有绑定?我将如何在模板中重用绑定处理程序?

绑定处理程序

define(['durandal/composition', 'plugins/http'], function (composition, http) {
    composition.addBindingHandler('dynamicSelect', {
        init: function (element, valueAccessor) {
            console.log(element);
            console.log(valueAccessor());
            var elem = $(element);
            elem.addClass('hidden');
            elem.before('<label>' + valueAccessor().label + '</label>');
            elem.after('<div><br/><label><i class="icon-spinner icon-spin active"></i> Loading...</label></div>');

            console.log('/api/lookup?type=' + valueAccessor().src);
            return http.get('/api/lookup?type=' + valueAccessor().src).then(function (res) {
                var items = res.LookupItems;
                $.each(items, function (idx) {
                    elem.append('<option value=' + items[idx].Id + '>' + items[idx].Name + '</option>');
                });
                elem.removeClass('hidden');
                elem.next().addClass('hidden');
            });

        },
        update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

        }
    });
});

【问题讨论】:

  • 好奇的问题,当我们有能力使用KO的时候,你为什么要使用jQuery来渲染视图?
  • 我对淘汰赛还很陌生,所以这是我最好的尝试...您能否提供代码/链接以其他方式处理我的视图,或提供代码以及您的建议也许?我所知道的是目前调用似乎没有在模板绑定期间执行..

标签: javascript knockout.js durandal


【解决方案1】:

发现我的问题。

我使用合成助手 Durandals 注册了绑定处理程序。因此(这是我最好的猜测),它只在页面创建期间被调用。解释为什么我的第一个选择被填充。

我将绑定处理程序更改为

define(['plugins/http'], function (http) {
    ko.bindingHandlers.dynamicSelect = {
        init: function (element, valueAccessor) {
            var elem = $(element);
            elem.addClass('hidden');
            elem.before('<label>' + valueAccessor().label + '</label>');
            elem.after('<div><br/><label><i class="icon-spinner icon-spin active"></i> Loading...</label></div>');

            console.log('/api/lookup?type=' + valueAccessor().src);
            return http.get('/api/lookup?type=' + valueAccessor().src).then(function (res) {
                var items = res.LookupItems;
                $.each(items, function (idx) {
                    elem.append('<option value=' + items[idx].Id + '>' + items[idx].Name + '</option>');
                });
                elem.removeClass('hidden');
                elem.next().addClass('hidden');
            });    
        }
    };
});

【讨论】:

    【解决方案2】:

    这并没有回答您与 durandal 相关的问题,但它解决了您在代码中缺乏 MVVM 思维方式的问题。 :D

    我会做它有一个 ViewModel

    MyApp.LookupViewModel = function(label, src) {
        this.label = label;
        this.src = src;
        this.items = ko.observableArray();   
        this.selectedItem = ko.observable();    
        this.loading = ko.observable(true);
        this.loaded = ko.computed(function() {
            return !this.loading();
        }, this);
    
    
        //simulate ajax
        setTimeout(function() {
            this.items([{
                    name: "Foo1",
                    id: 1
                },{
                    name: "Foo2", 
                    id: 2
                }
    
            ]);
            this.loading(false);
        }.bind(this), 1000);
    };   
    

    当你想使用它时,你只需声明一个虚拟机实例

    MyApp.ViewModel = function() {
        this.lookup = new MyApp.LookupViewModel("Foo", "http://foo");
    }
    

    http://jsfiddle.net/Vjzn6/1/

    我上面的小提琴使用了我的一个小库,负责查找视图名称,这样您就不需要在视图中显式声明模板绑定。

    【讨论】:

    • 重命名选项 > 项目以区别于 UI
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-22
    • 2016-03-31
    • 1970-01-01
    • 2013-03-14
    相关资源
    最近更新 更多