简体   繁体   English

使用knockout将数组元素数据绑定为值

[英]Data-bind an array element as value using knockout

Is there a way to bind a array element as a value of a input or a select? 有没有办法将数组元素绑定为输入值或选择值?

Something like this... 像这样......

 var ViewModel = function() { var self = this; self.array = ko.observableArray([undefined, undefined, undefined]); self.text = ko.computed(function() { return self.array()[0] + self.array()[1] + self.array()[2]; }); } var viewModel = new ViewModel(); ko.applyBindings(viewModel); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <input data-bind="value: $root.array[0]" /> <input data-bind="value: $root.array[1]" /> <input data-bind="value: $root.array[2]" /> <p data-bind="text: $root.text"></p> 

EDIT 编辑

Sorry guys, I'm really terrible to make questions, but my problem is a little more tricky, My real entries are selects that is a filter of an array and the values selecteds. 对不起,伙计们,我真的很难提出问题,但我的问题有点棘手,我的真实条目是选择,它是一个数组的过滤器和所选的值。 like this: 像这样:

 var ViewModel = function() { var self = this; self.family = ko.mapping.fromJS(data.family); self.array = ko.observableArray([ko.observable(undefined), ko.observable(undefined), ko.observable(undefined)]); self.filterFamily1 = function() { return self.family().filter(function(i) { return i.parent() == null; }); } self.filterFamily2 = ko.computed(function() { return ko.utils.arrayFilter(self.family, function(i) { return i.parent() === self.array()[0]().name(); }); }); self.filterFamily3 = ko.computed(function() { return ko.utils.arrayFilter(self.family, function(i) { return i.parent() === self.array()[1]().name(); }); }) } var data = { family: [{ name: "John", parent: null }, { name: "Mary", parent: null }, { name: "Erick", parent: "John" }, { name: "Paul", parent: "John" }, { name: "Marshall", parent: "Mary" }, { name: "Ross", parent: "Paul" }] }; var viewModel = new ViewModel(); ko.applyBindings(viewModel); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script> <select data-bind="options: $root.filterFamily1(),optionsText: 'name', value: $root.array()[0]"></select> <select data-bind="options: $root.filterFamily2(),optionsText: 'name', value: $root.array()[1]"></select> <select data-bind="options: $root.filterFamily3(),optionsText: 'name', value: $root.array()[2]"></select> 

but the answers were right for the problem that I describe before. 但答案适合我之前描述的问题。

Since your question changed a lot, I'm posting a new answer: 由于您的问题发生了很大变化,我发布了一个新答案:

Your snippet had console errors: your initially selected values weren't set nor did you check for undefined. 您的代码段有控制台错误:您最初选择的值未设置,也未检查未定义。 Include these checks and everything works. 包括这些检查,一切正常。

Do note that you can definitely improve readability and refactor recurring code sections. 请注意,您绝对可以提高可读性并重构重复的代码部分。

 var ViewModel = function() { var self = this; self.family = ko.mapping.fromJS(data.family); self.filterFamily1 = ko.computed(function() { return self.family().filter(function(i) { return i.parent() === null; }); }); self.array = ko.observableArray([ ko.observable(self.filterFamily1()[0]), ko.observable(undefined), ko.observable(undefined) ]); self.filterFamily2 = ko.computed(function() { return self.family().filter(function(i) { return self.array()[0]() && i.parent() === self.array()[0]().name(); }); }); self.filterFamily3 = ko.computed(function() { return self.family().filter(function(i) { return self.array()[1]() && i.parent() === self.array()[1]().name(); }); }) } var data = { family: [{ name: "John", parent: null }, { name: "Mary", parent: null }, { name: "Erick", parent: "John" }, { name: "Paul", parent: "John" }, { name: "Marshall", parent: "Mary" }, { name: "Ross", parent: "Paul" }] }; var viewModel = new ViewModel(); ko.applyBindings(viewModel); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script> <select data-bind="options: $root.filterFamily1(),optionsText: 'name', value: $root.array()[0]"></select> <select data-bind="options: $root.filterFamily2(),optionsText: 'name', value: $root.array()[1]"></select> <select data-bind="options: $root.filterFamily3(),optionsText: 'name', value: $root.array()[2]"></select> 

Yessir, there certainly is. Yessir肯定有。 But: 但:

  1. The items themselves must be observable s. 物品本身必须是observable的。
  2. You should execute the self.array function before binding to one of its elements. 您应该在绑定到其中一个元素之前执行self.array函数。

Here's an example: 这是一个例子:

 var ViewModel = function() { var self = this; self.array = ko.observableArray([ko.observable(""), ko.observable(""), ko.observable("")]); self.text = ko.computed(function() { return self.array()[0]() + self.array()[1]() + self.array()[2](); }); } var viewModel = new ViewModel(); ko.applyBindings(viewModel); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <input data-bind="value: $root.array()[0]" /> <input data-bind="value: $root.array()[1]" /> <input data-bind="value: $root.array()[2]" /> <p data-bind="text: $root.text"></p> 

However, why not use the foreach binding and some other nice improvements? 但是,为什么不使用foreach绑定和其他一些不错的改进?

 var ViewModel = function() { var self = this; self.array = ko.observableArray([ { txt: ko.observable("a") }, { txt: ko.observable("b") }, { txt: ko.observable("c") }, { txt: ko.observable("d") } ]); self.text = ko.computed(function() { return self.array().map(function(obs) { return obs.txt(); }).join(""); }); } var viewModel = new ViewModel(); ko.applyBindings(viewModel); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script> <!-- ko foreach: array --> <input data-bind="textInput: txt"> <!-- /ko --> <p data-bind="text: text"></p> 

If you want to access the array by index, you need to evaluate the observable first using () . 如果要按索引访问数组,则需要首先使用()来评估observable。

If you want the value binding to work two-ways (ie: not only set it initially, but also update the values in your viewmodel after a change), you'll have to bind them to ko.observable variables. 如果您希望value绑定以双向方式工作(即:不仅最初设置它,而且还在更改后更新viewmodel中的值),则必须将它们绑定到ko.observable变量。

Other improvements: 其他改进:

If you want to join all values together, you could use reduce or a combination of map and join to append the strings. 如果要将所有值连接在一起,可以使用reducemapjoin的组合来追加字符串。

EDIT: I was wrong here! 编辑:我错了! You could also use a foreach binding and use $data to refer to the current value if you need inputs for all your array's values. 如果需要输入所有数组的值,也可以使用foreach绑定并使用$data来引用当前值。

Actually, you can't create a two way binding using the $data keyword. 实际上,您无法使用$data关键字创建双向绑定。 You can if you use the $index observable. 如果使用$index observable,则可以。

Reference: https://github.com/knockout/knockout/issues/708 参考: https//github.com/knockout/knockout/issues/708

 var ViewModel = function() { var self = this; self.array = ko.observableArray([ko.observable("a"), ko.observable("b"), ko.observable("c")]); self.text = ko.computed(function() { return self.array()[0]() + self.array()[1]() + self.array()[2](); }); self.reducedText = ko.computed(function() { return self.array() .reduce(function(prev, curr) { return prev + curr(); }, ""); }); }; var viewModel = new ViewModel(); ko.applyBindings(viewModel); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <input data-bind="value: array()[0]" /> <input data-bind="value: array()[1]" /> <input data-bind="value: array()[2]" /> <p data-bind="text: text"></p> <!-- EDIT: this does not create a two way binding <div data-bind="foreach: array"> <input data-bind="value: $data" /> </div> --> <!-- EDIT: this does work --> <div data-bind="foreach: array"> <input data-bind="value: $parent.array()[$index()]" /> </div> <p data-bind="text: reducedText"></p> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM