【问题标题】:requirejs w/ knockoutjs w/ select2 fails to update observable on first loadrequirejs w/ knockoutjs w/ select2 无法在首次加载时更新 observable
【发布时间】:2015-01-09 17:57:31
【问题描述】:

我们第一次加载 requirejs 模块时,我的视图模型中的 observables 似乎没有更新。但是当您评论 $("#ddl").select2(); 时,一切正常。

requirejs.config({
    'paths': {
        'jquery': '//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.0.min',
            'ko': '//ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0',
            'select2': '//ivaynberg.github.io/select2/select2-3.4.5/select2',
            'domReady': 
                '//cdnjs.cloudflare.com/ajax/libs/require-domReady/2.0.1/domReady'
    },
        'shim': {
        'select2': {
            deps: ['jquery'],
            exports: '$.select2'
        }
    }
});

define('simpleKo', ['jquery', 'ko', 'domReady', 'select2'],

function ($, ko, domReady) {
    var simpleViewModel = function () {
        var self = this;
        self.name = ko.observable();
        self.names = ko.observableArray(['John', 'Tim', 'Mike', 'Jay']);
    };

    domReady(function () {
        ko.applyBindings(new simpleViewModel());
        $("#ddl").select2({
            width: 'resolve'
        });
    });
});

requirejs(['simpleKo']);

JSFiddle 上有一个实时示例,当您第一次打开没有缓存的链接时会失败。

我已经尝试了一切,有人对可能发生的事情有想法吗?

【问题讨论】:

    标签: knockout.js requirejs jquery-select2 amd


    【解决方案1】:

    我为 select2 使用自定义绑定处理程序(在引导环境中):

    <div data-bind="selectbox: { value: selectedValueId, values: values || [{id: 1, text: 'text'}], lookupId: 'id', lookupText: 'text', mode: 'id' }"/>
    

    尽管它可能看起来太复杂,但我在这里发布自定义绑定代码:

            ko.bindingHandlers["selectbox"] = {
            init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
                return { controlsDescendantBindings: true };
            },
            update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
                var nullValue = ["Unselected"];
    
                var options = valueAccessor(), value = options.value, values = (ko.unwrap(options.values) || []).map(function (item) {
                    return { id: ko.unwrap(item[options.lookupId || "id"]), text: ko.unwrap(item[options.lookupText || "text"]) || "(undelected)" };
                }), getId = (function (object) {
                    return object.id;
                }), findValue = options.findValue || (function (id) {
                    //console.log(id, values.filter((object) => { console.log(getId(object)); return getId(object) == id; }));
                    return values.filter(function (object) {
                        return (getId(object) == id) || (id == '' && getId(object) == null);
                    })[0];
                }), initialValue = (options.mode === "id" ? findValue(ko.unwrap(value)) : ko.unwrap(value)) || { text: "(undefined)" };
    
                //console.log(value());
                var $selectContainerTemplate = $("<div class='input-group' />");
                var $selectTemplate = $("<input type='hidden' style='width: 100%;' />");
                $selectContainerTemplate.append($selectTemplate);
    
                values = [{ id: null, text: "(undefined)" }].concat(values);
    
                $(element).children().remove();
                $(element).append($selectTemplate);
                $selectTemplate["select2"]({
                    initSelection: function (element, callback) {
                        callback(ko.unwrap(initialValue));
                    },
                    data: values,
                    id: getId
                });
                $selectTemplate.change(function (event) {
                    //alert(event.val);
                    var newValue = findValue(event["val"]);
                    if (options.mode === "id") {
                        newValue = newValue["id"];
                    }
                    if (ko.isObservable(value)) {
                        value(newValue);
                    } else {
                        value = newValue;
                    }
                });
            }
        };
    

    希望,这会有所帮助。

    【讨论】:

    • 我们在这里谈论的是同一个插件吗? select2
    • 当然。初始化代码是 "$selectTemplate["select2"]({ ... some options ... });",其中 "$selectTemplate" 是一个 jquery 包装器。作为项目列表,我使用 [{id: 1, text: 'text'}] 对象数组。我的案例是查找链接对象。
    • 我设法让它部分工作,它仍然没有选择正确的初始值。正在努力...
    • in options "selectbox: { value: selectedValueId ..." - "selectedValueId" 是模型中字段的名称,用作初始值和选定值所在的字段选择更改后存储
    • 当然可以,但我认为问题出在从服务器带来数据的 ajax 中。 select2 在 selectedValueId 获得任何实际值之前被绑定。即使完成请求,select2 也不会假定正确的值,但如果我手动设置,例如:svm.selectedId(5),则会触发更改事件
    【解决方案2】:

    一个更简单的方法是告诉 RequireJS KnockoutJS 依赖于 select2,即使这不是真的。

            'shim': {
                'select2': {
                    deps: ['jquery'],
                    exports: '$.select2'
                },
                'ko' : {
                    deps: ['select2']
                }
             }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-28
      • 2020-07-23
      • 2019-09-14
      • 2013-11-16
      • 1970-01-01
      • 2020-02-23
      相关资源
      最近更新 更多