2
votes

I have this code:

<script>
    var viewModel = {};

    $.getJSON("URL", function (data) {
        viewModel = ko.mapping.fromJS(data);
        ko.applyBindings(viewModel);
    });
</script>

I bind it in this code:

<!-- ko foreach: { data: object, as: 'object' } -->
   
   <div>
     ... content (with more data-bindings) ...
   </div>

<!-- /ko -->

But I get these errors in the console:

Uncaught TypeError: Unable to process binding "foreach: function(){return { data:object, as:'object'} }"

Message: Unable to process binding (...)

Message: Cannot read property (...)

I'm sure it's because the observable(s) are not pre-defined and by the time knockoutJS tries to bind them in, they're simply not existing.

I tried this:

var viewModel = {
    object: null
    (and other properties)
};

and this:

function viewModel() {
var self = this;
...
}

But it doesn't help. What am I doing wrong? I know there are plenty questions about that, but I can't find an answer to my problem.

1

1 Answers

0
votes

You're only applying bindings after your async data has returned. This isn't ideal, but it at least ensures there's no problem caused by binding to an initial empty object.

The way your view is set up requires your data that is received from the server to meet this requirement:

  • Must be an object
  • Must have a property object
  • The value of data.object must be iterable

I.e.: this should work:

ko.applyBindings({ object: [] })

If your data is an array, you should rewrite your binding to:

<!-- ko foreach: { data: $data, as: 'object' } -->
<div>Bind to object.someProp here</div>
<!-- /ko -->

If your data is an object, e.g.: { object: { a: 1 } }, you can remove the foreach or use a with binding.

Once you get this to work, you should try applying bindings with placeholder viewmodels before you start loading your data. This ensures a nice UI is rendered during load.