使用自定义绑定时如何更新 Knockout ViewModel
How to Update Knockout ViewModel when using a Custom Binding
我正在尝试将旋转框(带有递增和递减按钮的输入)连接到 KO,但我在确保用户与控件交互时我的 ViewModel 正确更新方面遇到了一些麻烦。
具体我用的控件是Fuel UX的SpinBox:http://getfuelux.com/javascript.html#spinbox
数据绑定本身附加到包装 div,因为它是整个控件的容器:
<div id="daysToComplete-spinner" data-initialize="spinbox" class="spinbox input-group" style="width: 150px;" data-bind="spinbox: daysToComplete, spinboxOptions: {min: 0, max: 180 }">
<input class="form-control spinbox-input" placeholder="Days">
<div class="spinbox-buttons input-group-btn">
<button type="button" class="btn btn-cancel spinbox-up">
<span class="fa fa-angle-up"></span><span class="sr-only">Increase</span>
</button>
<button type="button" class="btn btn-cancel spinbox-down">
<span class="fa fa-angle-down"></span><span class="sr-only">Decrease</span>
</button>
</div>
</div>
我写了一个绑定处理程序,似乎 运行 并构建了控件,但是 有几件事我很难实现:
- 我想注册一个事件处理器。当用户单击向上或向下按钮(跨度)时,我需要确保 ViewModel 的 属性 已更新为新值。我试过使用 valueAccessor(),但它给了我价值,而不是我期待的可观察到的 属性(在阅读 ko 网站上的文档之后)。
- 我想确保如果用户在输入框中键入数字,ViewModel 的 属性 会更新。数据绑定在 div 上,所以我假设 knockout 不会 "know" div 内的输入已更改...我该如何完成此操作?相同的事件处理程序?
这是我的处理程序目前的情况:
$(function () {
ko.bindingHandlers.spinbox = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var options = allBindingsAccessor().spinboxOptions || {};
$(element).spinbox(options);
var value = ko.utils.unwrapObservable(valueAccessor());
if (value) {
$(element).spinbox("value", value);
}
ko.utils.registerEventHandler(element, "changed.fu.spinbox", function (event, value) {
var modelValue = valueAccessor(),
modelValue(value); //it crashes here "not a function"
});
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).spinbox("value", value);
console.log(value);
}
};
});
任何关于我遗漏的指导都将不胜感激。
我不知道你的视图模型是什么样的,但你能确保你在之前的操作中没有用值覆盖可观察对象吗?
如果你在某个时候做了类似的事情:
viewmodel.daysToComplete = 4
然后 daysToComplete 属性 不再是可观察的。
结果 valueAccessor() 不会 return 一个可观察的,而是 4,这就是你所描述的。
我正在尝试将旋转框(带有递增和递减按钮的输入)连接到 KO,但我在确保用户与控件交互时我的 ViewModel 正确更新方面遇到了一些麻烦。
具体我用的控件是Fuel UX的SpinBox:http://getfuelux.com/javascript.html#spinbox
数据绑定本身附加到包装 div,因为它是整个控件的容器:
<div id="daysToComplete-spinner" data-initialize="spinbox" class="spinbox input-group" style="width: 150px;" data-bind="spinbox: daysToComplete, spinboxOptions: {min: 0, max: 180 }">
<input class="form-control spinbox-input" placeholder="Days">
<div class="spinbox-buttons input-group-btn">
<button type="button" class="btn btn-cancel spinbox-up">
<span class="fa fa-angle-up"></span><span class="sr-only">Increase</span>
</button>
<button type="button" class="btn btn-cancel spinbox-down">
<span class="fa fa-angle-down"></span><span class="sr-only">Decrease</span>
</button>
</div>
</div>
我写了一个绑定处理程序,似乎 运行 并构建了控件,但是 有几件事我很难实现:
- 我想注册一个事件处理器。当用户单击向上或向下按钮(跨度)时,我需要确保 ViewModel 的 属性 已更新为新值。我试过使用 valueAccessor(),但它给了我价值,而不是我期待的可观察到的 属性(在阅读 ko 网站上的文档之后)。
- 我想确保如果用户在输入框中键入数字,ViewModel 的 属性 会更新。数据绑定在 div 上,所以我假设 knockout 不会 "know" div 内的输入已更改...我该如何完成此操作?相同的事件处理程序?
这是我的处理程序目前的情况:
$(function () {
ko.bindingHandlers.spinbox = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var options = allBindingsAccessor().spinboxOptions || {};
$(element).spinbox(options);
var value = ko.utils.unwrapObservable(valueAccessor());
if (value) {
$(element).spinbox("value", value);
}
ko.utils.registerEventHandler(element, "changed.fu.spinbox", function (event, value) {
var modelValue = valueAccessor(),
modelValue(value); //it crashes here "not a function"
});
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).spinbox("value", value);
console.log(value);
}
};
});
任何关于我遗漏的指导都将不胜感激。
我不知道你的视图模型是什么样的,但你能确保你在之前的操作中没有用值覆盖可观察对象吗?
如果你在某个时候做了类似的事情:
viewmodel.daysToComplete = 4
然后 daysToComplete 属性 不再是可观察的。 结果 valueAccessor() 不会 return 一个可观察的,而是 4,这就是你所描述的。