[英]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:
但:
observable
s. observable
的。 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. 如果要将所有值连接在一起,可以使用
reduce
或map
和join
的组合来追加字符串。
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.