0

I have trouble trying to map data in a nested observableArray (timeSlots). When I fill my participants observableArray it works just fine. I bet I have to do something special when it's nested.

I'm new to Knockout so not sure what I am doing wrong. I've been looking at the documentation to no avail, especially at:

http://knockoutjs.com/documentation/plugins-mapping.html

Here is my code: (EDITED)

<script type="text/javascript">

var TimeSlot = function (startTime, endTime) {
    var self = this;
    self.startTime = startTime;
    self.endTime = endTime;
};

var Participant = function (id, timeSlots) {
    var self = this;
    self.Name = id;
    self.roomName = ko.observable();
    self.timeSlots = ko.observableArray();

    var timeSlotVMs = _.map(timeSlots, function(ts) {
        return new TimeSlot(ts.startTime, ts.endTime);
    });

    ko.utils.arrayPushAll(self.timeSlots(), timeSlotVMs);
};

function ViewModel() {
    var self = this;
    self.participants = ko.observableArray([]);

    self.addPerson = function () {
         var data = '{"TimeSlot":[{"startTime":"05:23","endTime":"06:32"},
                     {"startTime":"10:23","endTime":"11:32"}]}';
         var partViewModel = new Participant(self.selectedValue().Id(), data.TimeSlot);
         self.participants.push();
    };
};



var viewModel = new ViewModel();
ko.applyBindings(viewModel);

</script>

And HTML if needed:

<tbody data-bind="foreach: viewModel.participants">
    <tr>
        <td data-bind="text: Name"></td>
        <td data-bind="text: roomName"></td>

        <td data-bind="foreach: viewModel.participants.timeSlots">
                <span data-bind="text: startTime"></span>
        </td>
    </tr> 
</tbody>
1

1 Answer 1

1

Try this:

var TimeSlot = function (startTime, endTime) {
    var self = this;
    self.startTime = startTime;
    self.endTime = endTime;
};

var Participant = function (id, timeSlots) {
    var self = this;
    self.Name = id;
    self.roomName = ko.observable();
    self.timeSlots = ko.observableArray();

    var timeSlotVMs = _.map(timeSlots, function(ts) {
        return new TimeSlot(ts.startTime, ts.endTime); 
    });
    ko.utils.arrayPushAll(self.timeSlots(), timeSlotVMs);        
};

function ViewModel() {
    var self = this;
    self.participants = ko.observableArray();

    self.addPerson = function () {
         var data = {
             TimeSlot: [
               {startTime:"05:23",endTime:"06:32"},
               {startTime:"10:23",endTime:"11:32"}
            ]
         };
         var partViewModel = new Participant(123, data.TimeSlot);
         self.participants.push(partViewModel);
    };
};

I used lodash library function 'map', to create array of viewmodels.

Also, you have error in your layout. Use timeSlots instead viewModel.participants.timeSlots:

<tbody data-bind="foreach: participants">
    <tr>
        <td data-bind="text: Name"></td>
        <td data-bind="text: roomName"></td>

        <td data-bind="foreach: timeSlots">
            <span data-bind="text: startTime"></span>
        </td>
    </tr> 
</tbody>
Sign up to request clarification or add additional context in comments.

5 Comments

I had to modify to var timeSlotVMs = _.map(timeSlots, function(ts) { return new TimeSlot(ts.startTime, ts.endTime); }); to make it run, however I am still not getting it to work
Can you update your question with new code? Or create it here
Removed the "viewModel.participants.timeSlots" and just wrote timeSlots. Still not working I'm afraid. <td data-bind="foreach: timeSlots"><span data-bind="text: startTime"></span></td>
I've updated my answer again and created a working demo
Sorry for the late reply. It works with your solution thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.