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?

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

5 Comments

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.
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...
I would probably just do a manually mapping like: 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?
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!
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: <div data-bind="foreach: ArrayOfModels"> <div data-bind="text: Fullname"></div> <div data-bind="foreach: ArrayOfModels"> <div data-bind="text: Fullname"></div> </div> And then update when the data is present?

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.