requirejs w/ knockoutjs w/ select2 无法在首次加载时更新 observable
Posted
技术标签:
【中文标题】requirejs w/ knockoutjs w/ select2 无法在首次加载时更新 observable【英文标题】:requirejs w/ knockoutjs w/ select2 fails to update observable on first load 【发布时间】: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 上有一个实时示例,当您第一次打开没有缓存的链接时会失败。
我已经尝试了一切,有人对可能发生的事情有想法吗?
【问题讨论】:
【参考方案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']
【讨论】:
以上是关于requirejs w/ knockoutjs w/ select2 无法在首次加载时更新 observable的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 jQuery、RequireJS 和 KnockoutJS 创建基本的 TypeScript 项目
Karma + Jasmine + Durandal + KnockoutJS + RequireJS 单元测试中不匹配的匿名 define() 模块