6

I have a view which contains a template that has a foreach to loop round an array of models. However, the array of models comes from an ajax call.

Here is an example of the scenario:

// Contained Model
function SomeModel() {
    var self = this;
    this.Firstname = ko.observable();
    this.Lastname = ko.observable();
    this.Fullname = ko.dependentObservable(function() {
        return this.Firstname + " " + this.Lastname;
    }, self);
}

// View Model
function SomeViewModel() {
    var self = this;

    this.ArrayOfModels = ko.mapping.fromJS([]);

    this.GetModelsByAjax = function() {
        $.ajax(...);
    };

    this.SuccessfullyRetrievedModelsFromAjax = function(models) {
        ko.mapping.updateFromJS(self.ArrayOfModels, models);
    };
}

ko.applyBindings(new SomeViewModel());

Here's the View:

<HtmlGuff>
    <div data-bind="template: {name: 'model-template', foreach: ArrayOfModels}"></div>
</HtmlGuff>

// Template
<HtmlGuff>
    <h2 data-bind="text: Fullname">
    <div data-bind="text: Firstname" />
    <div data-bind="text: Lastname" />
</HtmlGuff>

And this is the json result from the ajax call:

[{
    "Firstname": "Joe",
    "Lastname": "Blogs"
}, {
    "Firstname": "Foo",
    "Lastname": "Bar"
}]

Currently I am just passing in [] to the model declaration, however I keep getting the following error:

Firstname is not defined

It breaks on this: return new Function("jQuery","$item", body);.

Is there any way to do what I want to?

Jeroen
  • 60,696
  • 40
  • 206
  • 339
somemvcperson
  • 1,263
  • 2
  • 18
  • 31

1 Answers1

3

What you are trying to do seems fine to me.

Here is a sample with it working: http://jsfiddle.net/rniemeyer/ENMGp/ that you could maybe try to reconcile against.

I don't know exactly what your "models" look like coming back from your AJAX call though.

These lines are missing an =, but I assume that is just a typing error and would not result in the error that you listed.

<div data-bind"text: Firstname" />
<div data-bind"text: Lastname" />

I think that your best bet would be to do some logging on the models being returned by your web service and make sure that they are not nested in a way that you are not expecting.

Would be happy to continue helping, if you have more info on the result of your AJAX call or any other clues.

RP Niemeyer
  • 114,592
  • 18
  • 291
  • 211
  • Sorry this was an abstract example, there is one other key thing I missed out which will kinda show why I need to use the model, and not just the Json result. – somemvcperson Jul 10 '11 at 07:19
  • Updated initial question to more accurately reflect the underlying problem, where I need to have access to a dependable function on the model, but need the data to come from ajax... Its more like most static languages where the structure is defined in one place, and the data is defined elsewhere... – somemvcperson Jul 10 '11 at 10:45
  • I would probably just do a manually mapping like: http://jsfiddle.net/rniemeyer/tD4pH/. Otherwise, it is possible to use the `create` callback in the mapping options, but probably not necessary here unless you are going to be continuously updating from the mappin plugin. Does this work for you? – RP Niemeyer Jul 10 '11 at 15:12
  • The manual mapping should be ok for now, the mapping wont be updated once displayed in this instance. Although others maybe... thanks alot for your examples! – somemvcperson Jul 10 '11 at 17:01
  • In your example, you have a contained model (which is not used in the jsfiddle), and I noticed you are using a template. Why doesn't this work:
    And then update when the data is present?
    – John Mann Jun 01 '15 at 15:15