Javascript Question

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.

Answer

Yessir, there certainly is. But:

  1. The items themselves must be observables.
  2. You should execute the self.array function before binding to one of its elements.

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?

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>

Comments