2

I want to bind and change multiple inputs to the same variable (so that they will always change together to the same value), but I can not figure this out. My code:

        $(function () {
            var AppVm = function () {
                this.people = ko.observableArray([
                    { firstName: 'Bert', lastName: 'Bertington' },
                    { firstName: 'Charles', lastName: 'Charlesforth' },
                    { firstName: 'Denise', lastName: 'Dentiste' }
                ]);
            };
            vm = new AppVm();
            ko.applyBindings(vm);
        });
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
        <thead>
            <tr><th>First name</th><th>Last name</th></tr>
        </thead>
        <tbody data-bind="foreach: people">
            <tr>
                <td>
                <input type="text" data-bind="textInput: firstName"/>
                </td>
                <td>
                <input type="text" data-bind="textInput: firstName"/>
                </td>
            </tr>
        </tbody>
    </table>

It loads the same value initially in both the text inputs, but when I change one of them , the other one does not update. How can I update them both at the same time?

Harsh Shah
  • 667
  • 5
  • 22
  • 1
    Your properties must be observable in order to update with knockout. Making the whole array observable doesn't make the individual properties observable. ObservableArrays only react to changes in the array size. – Jason Spake Apr 13 '18 at 15:42
  • I figured it's something like that. But is there any way I can make individual properties observable for the whole observable array? – Harsh Shah Apr 13 '18 at 17:15
  • There isn't any built in way to automatically do that, but there is a commonly used library that helps called the ko.mapping plugin. http://knockoutjs.com/documentation/plugins-mapping.html – Jason Spake Apr 13 '18 at 18:41

1 Answers1

2

As Jason Spake said in the comments:

Your properties must be observable in order to update with knockout. Making the whole array observable doesn't make the individual properties observable. ObservableArrays only react to changes in the array size.

You therefore need to used ko.observable() inside the observableArray for the changes to be detected:

$(function () {
    var AppVm = function () {
        this.people = ko.observableArray([
            { firstName: ko.observable('Bert'), lastName: ko.observable('Bertington') },
            { firstName: ko.observable('Charles'), lastName: ko.observable('Charlesforth') },
            { firstName: ko.observable('Denise'), lastName: ko.observable('Dentiste') }
        ]);
    };
    vm = new AppVm();
    ko.applyBindings(vm);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<table>
    <thead>
        <tr><th>First name</th><th>Last name</th></tr>
    </thead>
    <tbody data-bind="foreach: people">
        <tr>
            <td>
                <input type="text" data-bind="textInput: firstName"/>
            </td>
            <td>
                <input type="text" data-bind="textInput: firstName"/>
            </td>
        </tr>
    </tbody>
</table>

Now when you change a value in the left input, in will change it in the right one as well at the same time.

Adam Jaamour
  • 1,326
  • 1
  • 15
  • 31
  • 1
    Thanks, this works. I wanted to generalize it a little more and I found the solution here at https://stackoverflow.com/questions/10048553/knockoutjs-observable-array-of-observable-objects in the second answer (by Andy Thomas) – Harsh Shah Apr 17 '18 at 18:29
  • @HarshShah Oh yes I see, this does make it easier to manipulate, good answer! – Adam Jaamour Apr 17 '18 at 18:36