2
votes

I'm having a bit of an issue with Knockout.js and its mapping plugin. Essentially I want to start with no data, and then on page load make an Ajax request to load in the information. I know that the Ajax request is working as intended cause I'm logging to the console the data as it's being returned.

    var projectId = @Model.Project.Id;
    var stories;
    viewModel = ko.mapping.fromJS(stories);       

    $.ajax({
        type: "GET",
        url: "/Projects/JsonDetails",
        data: {id: projectId},
        success: function (data) {
            stories = data.stories;
            ko.mapping.fromJS(stories, viewModel);
            console.log(stories);
        }
    });

The console is logging the the data correctly. so I know that the Ajax request is working properly.

The console is logging the the data correctly. so I know that the Ajax request is working properly. l

View Markup:

   <section id="project-stories"  data-bind="foreach: stories">

            <div class="project-story-container drop-shadow">

                <div class="story-summary">
                    Story Summary
                </div>
                <div class="story" data-bind="attr:{'data-id': Id}">
                    As a <span  class="actor" data-bind="text: Actor"> </span> I want to <span  class="objective" data-bind="text: Objective"> </span>, so that  <span  class="justification" data-bind="text: Justification"></span>.
                </div>
                <div class="story-controls">
                    <a href="#">Edit</a>
                </div>
            </div>
        </section>

I've even tried calling:

   var projectId = @Model.Project.Id;
    var stories;
    viewModel = ko.mapping.fromJS(stories);
     ko.applyBindings(viewModel);

    $.ajax({
        type: "GET",
        url: "/Projects/JsonDetails",
        data: {id: projectId},
        success: function (data) {
            stories = data.stories;
            ko.mapping.fromJS(stories, viewModel);
            console.log(stories);
        }
    });

But that just makes it worse cause KO complains that the bindings aren't setup. enter image description here

Can anyone see what I'm doing wrong? Eventually I want the view model to have more events wired in, which I know will be another challenge. But right now I can't even get the bindings to update properly when the Ajax request finishes.

Going off the tutorial here: http://knockoutjs.com/documentation/plugins-mapping.html

-------------------- UPDATE --------------------------

I was able to answer my own question by referencing this StackExhange Post:

Knockout JS mapping plugin confusion

var projectId = @Model.Project.Id;
    var viewModel ={};
    $.ajax({
        type: "GET",
        url: "/Projects/JsonDetails",
        data: {id: projectId},
        success: function (data) {
            viewModel.stories = ko.mapping.fromJS(data.stories);
            ko.applyBindings(viewModel);
        }
    });

Problem was I needed to have an empty view model for this to work.

2

2 Answers

0
votes

The problem is in the way you're doing the mapping. You shouldn't map data.stories but data itself ko.mapping.fromJS(data, viewModel); That way the mapping pluging will create an observable array for stories that you can then use in your template.

If data contains other elements that you don't want to map, you can add them to the ignore array so only stories is mapped.

One more thing - if you're starting with no data you will get this error on page load because Knockout will try to map stories in your view model when such property doesn't exist. Define your viewmodel ahead of time to contain stories as observable array.

0
votes

@Marek Karbarz Hi, I do not believe that you should be passing the entire viewModel. For example, if you have a model for the page, the model has a SearchCriteria object and the Results object. Why would you want to pass the Results object back when you only need to do a search?

-Edward