Bmo
Bmo

Reputation: 1212

Knockout foreach binding not rendering anything

I have, what I thought was a fairly straightforward knockout situation. I have a model that comes in from WebApi that has an array of things with a Success element. I need the value of success to determine what of the properties render. I've validated that all the data is coming down from WebApi ok but nothing but the table shell renders. There are no errors in the dev console.

The HTML

<div id="model1Wrapper">
<table class = "table">
    <thead >
        <tr >
            <th >Stuff</th><th>Things</th> 
        </tr> 
    </thead>
    <tbody data-bind = "foreach: $data.historyArray" >
        <!--ko if: Success -->
        <tr class = "success" >
            <td data-bind = "text: $data.ThingA" > </td>
            <td data-bind = "text: ThingB" > </td> 
        </tr>
        <!-- /ko -->

        <!--ko ifnot: Success -->
        <tr class = "danger" >
            <td colspan="3" data-bind = "text: ThingC" > </td>
        </tr>
        <!-- /ko -->
    </tbody> 
</table>
</div>

Example Model Data

[{
    "ThingA": "A",
    "ThingB": "B",
    "ThingC": "C",
    "Success": false
}, {
    "ThingA": "A",
    "ThingB": "B",
    "ThingC": "C",
    "Success": true
}]

This is monitoring a process that has feeds from several endpoints so I have multiple ViewModels on the page. So I framed up a rough example of how that is working elsewhere on the page.

That business

<script>
    var sampleModelData = [{
        "ThingA": "A",
        "ThingB": "B",
        "ThingC": "C",
        "Success": false
    }, {
        "ThingA": "A",
        "ThingB": "B",
        "ThingC": "C",
        "Success": true
    }]


    var viewModel1 = {
        historyArray: ko.observableArray()
    };

    function onNewHistory(data) {
        viewModel1.historyArray(data);
    }

    $(document).ready(function(){
        ko.applyBindings(viewModel1, document.getElementById("model1Wrapper"));
        onNewHistory(sampleModelData);
    })

</script>

I had to mask of some of the speciffics but the gist is, the ajax call returns an array in the example. There is a function that is called to update the new data into the observable and I would expect the table to rerender, it does not.

Other deets

Thanks!

Upvotes: 0

Views: 998

Answers (2)

Jamie Lupton
Jamie Lupton

Reputation: 118

Just adding another answer to this question in case someone comes across it in future. I had this issue and it was a result of initialising my observable array within the method. I didn't mean to do this (copy paste error) and it didn't produce any errors in the console so was difficult to trace.

For example:

LoadJSArrayIntoObservable(results) {
    vm.validationResults = ko.observableArray();  <---- THIS IS INVALID. 
    vm.validationResults([]);  <---- THIS IS WHAT I MEANT TO DO!!

    $.each(results, function () {
        try {
            vm.validationResults.push(new ValidationResult(this));
        }
        catch (err) {
            alert(err.message);
        }
    });

Upvotes: 0

Justin Grant
Justin Grant

Reputation: 46763

The problem is in this code:

var viewModel1 = {
    historyArray = ko.observableArray();
}

You're mixing the syntax for declaring objects with the syntax for code inside functions. When declaring an object, don't use = and ;. Instead use : and ,.

If you change the declaration to something like below, it should work.

var viewModel1 = {
    historyArray: ko.observableArray()
}

Upvotes: 4

Related Questions