简体   繁体   中英

KnockoutJS: Nested observableArrays and Nested ForEach

disclaimer- I fear this question may be a duplicate, because the functionality seems so basic, so I know I'll probably get a dupe ding. But I couldn't find a solution that worked

So I have an observable array setup as follows

self.meetingAttendees = ko.observableArray([
    {
        AttendeeTypeId: ko.observable(1),
        AttendeeNames: ko.observableArray([
            { Name: ko.observable("Nemo"), CurrentEdit: ko.observable(0) }
        ]),
        AttendeeSiteNumber: ko.observable(""),
        StudentNames: ko.observableArray([
            { Name: ko.observable("Flava Flave"), CurrentEdit: ko.observable(1) }
        ]),
        Email: ko.observable(""),
        Telephone: ko.observable("")
    }]);

and my "problem" HTML is:

<tbody data-bind="foreach: $root.meetingAttendees">
    <tr>
        <td class="attendeeNameCol textAlignCenter">
            <div class="textAlignCenter" data-bind="foreach:{data: AttendeeNames, as: 'Attendee'}">
                 <input class="formInput" data-bind="textInput: Attendee.Name()"/>
                 <span class="glyphicon glyphicon-remove nameRemove" data-bind="click:$root.removeName.bind($data,$index(),'AttendeeNames',$parentContext.$index())"></span>
            </div>
            <span data-bind="visible:$root.meetingAttendees()[$index()].AttendeeTypeId() == 1,click:$root.addName.bind($data,$index(),'AttendeeNames',$index())" class="addAnotherText">(+) Add Another Parent</span>
         </td>
    </tr>
</tbody>

Everything thing seems to work fine and with the dummy data, it binds correctly. But, when I push an element into AttendeeNames

self.meetingAttendees()[parentIndex].AttendeeNames().push( {Name: ko.observable(""),CurrentEdit: ko.observable(1)} );

my view does not insert another element. I check the array and it does show that an element has been added, so I believe it is a binding issue.

My question is how can I bind correctly so that the nested foreach statements properly update and display the information in the nested observableArrays?

:(

The answer is far too simple.

self.meetingAttendees()[parentIndex].AttendeeNames().push(
    {Name: ko.observable(""),CurrentEdit: ko.observable(1)}
);

does not push into the array.

I shouldn't be using AttendeeNames().push()

It needs to be AttendeeNames.push()

I made the same mistakes on my bindings. I was doing Attendee.Name() instead of Attendee.Name as I should have.

If anyone wants to describe why this happens, I'll accept their answer as I do not know the exact logic as to why.

So, AttendeeNames is aa knockout observable array. If you do a console.log on it, you'll notice you get a function back instead of an array. This variable can actually be used in two ways.

If you call it as AttendeeNames() , you are getting the underlying array without any of the knockout functionality. So you can modify this underlying array all you want, and print it out, and it will look like the data is changing, but your view won't update because knockout has no way of knowing about these changes. You can manually notify the observable of this change by using AttendeeNames.valueHasMutated() . Notice how it is using the Knockout functionality - no () after AttendeeNames . Sometimes this can be useful if you think you may be making a large number of changes and you don't want to update the view until everything is complete for performance reasons.

When you call AttendeeNames.push() , you are actually using the knockout functionality, which adds the item to the underlying array and notifies the view that it needs to update.

Recap:

The following snippets have the same functionality:

AttendeeNames.push(item);

AttendeeNames().push(item);
AttendeeNames.valueHasMutated();

By accessing a knockout observable using () , you are bypassing all the knockout stuff and getting the encapsulated Javascript value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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