1

I have a view Model in Knockout that is mapped using the mapping plugin. I need to do so since the data (a JSON object) will be retrieved from a server using Ajax calls.

My problem is that when I modify a form, the mapped data isn't updated in the object...

You can also see this in action the following JSFiddle: http://jsfiddle.net/etiennenoel/4EXSy/6/

Here's my object retrieved from the server:

var dataContent = 
[
    {
        playerId: 2,
        playerName: "allo",
        evaluatedExercises: 
        [
            {
                id: 1,
                evaluationExerciseId: 1,
                numberOfTries: 6,
                tries: [
                    {
                    id: 0,
                    number: 0,
                    result: 0
                    }
                ]
            }       
        ]
    }
]

Here is the complete javascript view model:

function Try(id, number, result) {
    var self = this;

    self.id = id;
    self.number = number;
    self.result = result;
}

function ExerciseResult(id, evaluationExerciseId) {
    var self = this;

    self.id = id;
    self.evaluationExerciseId = evaluationExerciseId;
    self.tries = [];
}

function PlayerEvaluation(playerId, playerName) {
    var self = this;

    self.playerId = playerId;
    self.playerName = playerName
    self.evaluatedExercises = [];
}

function appViewModel() {
    var self = this;

    self.playersEvaluation = ko.observableArray();

    self.exportToJSON = ko.computed(function() {
        return ko.toJSON(self.playersEvaluation);
    }, this);

}

var viewModel = new appViewModel();

var dataContent = 
[
    {
        playerId: 2,
        playerName: "allo",
        evaluatedExercises: 
        [
            {
                id: 1,
                evaluationExerciseId: 1,
                numberOfTries: 6,
                tries: [
                    {
                    id: 0,
                    number: 0,
                    result: 0
                    }
                ]
            }       
        ]
    }
]

for(i = 0; i < dataContent.length; i++) {
    playerEvaluation = new PlayerEvaluation(dataContent[i].playerId, dataContent[i].playerName);

    evaluatedExercises = dataContent[i].evaluatedExercises;

    for(j = 0; j < evaluatedExercises.length; j++) {    
        exerciseResult = new ExerciseResult(evaluatedExercises[j].id, evaluatedExercises[j].evaluationExerciseId);
        tries = evaluatedExercises[j].tries;

        for(k = 0; k < tries.length; k++) {
            exerciseTry = new Try(tries[k].id, tries[k].number, tries[k].result)

            exerciseResult.tries.push(exerciseTry);
        }

        playerEvaluation.evaluatedExercises.push(exerciseResult);        
    }

   viewModel.playersEvaluation.push(playerEvaluation);
}

ko.mapping.fromJS(viewModel.playersEvaluation);
ko.applyBindings(viewModel)

This object is mapped in html using KnockoutJS:

    <table class="table table-hover table-bordered">
     <thead> <!-- This will be generated with Twig so it is normal that is does not correspond to the data below -->
         <tr>
             <th>Nom</th>
             <th colspan="6" style="text-align:center">Élément #1</th>

         </tr>
         <tr>
             <th></th>

             <th class="try">
                 1                 
             </th>
             <th class="try">
                 2                 
             </th>
             <th class="try">
                 3                 
             </th>
             <th class="try">
                 4                 
             </th>
             <th class="try">
                 5                 
             </th>
             <th class="try">
                 6                 
             </th>  

         </tr>
    </thead>
    <tbody data-bind="foreach: playersEvaluation">
        <tr data-bind="">
            <td data-bind="text: $data.playerName">
            </td>
           <!-- ko foreach: $data.evaluatedExercises -->
            <!-- ko foreach: $data.tries -->
            <td>
                <input type="text" data-bind="value: $data.result" />
            </td>
            <!-- /ko -->
            <!-- /ko -->
        </tr>
    </tbody>
</table>


<div data-bind="text: exportToJSON()">

</div>

When I modify the input, I want the changes to be reflected in the self.playersEvaluation variable of my viewModel. To do so, I created a computed Function that shows the content of the playersEvaluation in a div below the table.

However, the div does not get updated and therefore I came to the conclusion that the mapping must not be proper.

Where my mapping has gone wrong ?

2
  • What is your problem, eventually? Commented Jul 4, 2013 at 14:52
  • When I modify the input, the changes does not get reflected in the div, therefore the mapping is not properly done... Commented Jul 4, 2013 at 14:53

1 Answer 1

2

im not incredibly experienced with the mapping plugin, but i believe you should just let it build your view model structure for you (since you dont appear to have any more complex logic at any level of your view models)

http://knockoutjs.com/documentation/plugins-mapping.html

function appViewModel() {
    var self = this;
    self.playersEvaluation;   
}

var viewModel = new appViewModel();

// this creates observables for everything in dataContent. the result itself is an observable
// which you can set in your top level view model
viewModel.playersEvaluation = ko.mapping.fromJS(dataContent)
ko.applyBindings(viewModel);

Fiddle: http://jsfiddle.net/4EXSy/8/

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

1 Comment

That does it ! Thank you !

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.