javascript 淘汰赛 - 向 ko.computed 写入一个值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24062330/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Knockout - write a value to a ko.computed
提问by leaksterrr
I've built a very data/number heavy app in Knockout. I'm currently getting the error:
我在 Knockout 中构建了一个非常数据/数字的应用程序。我目前收到错误:
Uncaught Error: Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.
未捕获的错误:除非您指定“写入”选项,否则无法将值写入 ko.computed。如果您希望读取当前值,请不要传递任何参数。
This is happening when my custom bindingHandler (which formats the numbers into 'large' form, ie. 123,345,678,987) tries to write back to the original input which displays the value of a computed function.
当我的自定义 bindingHandler(将数字格式化为“大”形式,即 123,345,678,987)尝试写回显示计算函数值的原始输入时,就会发生这种情况。
Value displayed in an input element:
输入元素中显示的值:
self.value = ko.computed(function(){
return self.chosenAge().population; // 'fetched' from an array.
});
Binding Handler:
绑定处理程序:
ko.bindingHandlers.largeNumber = {
init: function(element, valueAccessor) {
numberInit(element);
var value = valueAccessor();
var interceptor = ko.computed({
read: function() {
// inject number formatting
return numeral(ko.unwrap(value)).format('0,0');
},
write: function(newValue) {
// remove formatting when writing a new value
value(numeral().unformat(newValue));
}
});
// display new value in target element
if(element.tagName.toLowerCase() == 'input' ) {
ko.applyBindingsToNode(element, {
value: interceptor
});
}
else {
ko.applyBindingsToNode(element, {
text: interceptor
});
}
}
};
回答by Zack Huber
You need to specify a 'write' option in your ko.computed function. Please see the documentation on computed observables. Your binding handler has nothing to do with your value failing to update. Your computed should look something like this:
您需要在 ko.computed 函数中指定一个 'write' 选项。请参阅有关计算的 observables的文档。您的绑定处理程序与您的值无法更新无关。你的计算应该是这样的:
self.value = ko.computed(function(){
read: function () {
return self.chosenAge().population; // 'fetched' from an array.
},
write: function (value) {
//update your self.chosenAge().population value here
},
owner: self
});
Hope this helps.
希望这可以帮助。
回答by Origineil
Personally, I would capture the implementation of your formatting in an extender
.
就个人而言,我会在extender
.
Define an extension that wraps the data observable with a computed
formatter:
定义一个用computed
格式化程序包装可观察数据的扩展:
ko.extenders.largeNumber = function (target, option) {
var formatter = ko.computed( {
read: function(){
var formatted = target().toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return formatted;
},
write: function(nv){
var numeric = nv.replace(/,/g,"");
target(numeric);
console.log("View model now contains " + target())
}
})
return formatter;
};
Then create an observable that uses the extension: (I've wrapped it in a constructor)
然后创建一个使用扩展名的 observable :(我已经将它包装在一个构造函数中)
function createExtendedObs(initialValue){
return ko.observable(initialValue).extend({
largeNumber: {
viewModel: self
}
});
In addition, I would make my observable be the population
property within the data object that represents a chosenAge
此外,我会让我的 observable 成为population
数据对象中代表一个chosenAge
{
name: "Bronze",
population: createExtendedObs(10000)
}
This is not a requirement.If you want the population to be stored in another observable, I setup the extender to have access to the viewModel through the options
parameter. Thus, you would access the other observable that way. If the "other" observable were to be a computed, then you would need to specify the write
function (as depicted in the other answer) which is the root of the issue you are having. Another option would be to subscribe
to chosenAge
and set the "other" population observable from within the subscription.
这不是必需的。如果您希望将人口存储在另一个 observable 中,我将扩展程序设置为可以通过options
参数访问 viewModel 。因此,您将以这种方式访问另一个 observable。如果“其他”可观察量是计算的,那么您需要指定write
函数(如另一个答案中所述),这是您遇到的问题的根源。另一种选择是subscribe
,以chosenAge
并设置了“其他”人口从认购可观察到。
Using the data property directly, I am able to bind to it as follows,
直接使用 data 属性,我可以如下绑定到它,
<div data-bind='with: chosenAge'>
<input data-bind='value: population'></input>
</div>
Check out my fiddlefor the full setup.
查看我的小提琴以获得完整的设置。
Edit
编辑
Just reviewed a comment about wanting to enter the value "with" the formatting. The field will be formatted each time the computed receives a new value. By default, this will be on focus loss. If you want to modify it as the input is provided then you would need to provide the valueUpdate
binding parameter. Since the field is being manipulated dynamically this will cause caret positioning issues. You would need to manage the caret position accordingly.
刚刚查看了关于想要输入“带有”格式的值的评论。每次计算收到新值时,该字段都会被格式化。默认情况下,这将是焦点损失。如果要在提供输入时修改它,则需要提供valueUpdate
绑定参数。由于该字段是动态操作的,这将导致插入符号定位问题。您需要相应地管理插入符号位置。
<input data-bind='value: population, valueUpdate: "afterkeydown"'></input>