Brian M. Hunt
Brian M. Hunt

Reputation: 83848

Knockout.js mapping plugin does not call 'create' or 'update' properties of arrays in objects

Where an array is nested within an object the 'create' and 'update' callbacks of the Knockout.js mapping plugin are not called when one would expect. In particular, one would expect that calling the view_model.mappedCreate({}) would trigger the callbacks.

Here is an example, given a data structure and mapping like this:

var data = {
    Test: {
        Items: [
            { Name: "Red", Count: 0},
            { Name: "Green"}
        ]
    },
    NewItem: ""
},
    counter = 0;


var vm = ko.mapping.fromJS(data, {
    Test: {
        Items: {
            create: function(options) {
                options.data.Count = ++counter;
                console.log("Data:", options.data);
                return ko.mapping.fromJS(options.data);
            },
            update: function(options) {
                options.data.Count = ++counter;
                console.log("Data:", options.data);
                return ko.mapping.fromJS(options.data);
            }
        }
    }
});

As you can see from this jsFiddle, the output of the above is:

{
  "Test": {
    "Items": [
      {
        "Name": "Red",
        "Count": 0
      },
      {
        "Name": "Green"
      }
    ]
  },
  "NewItem": ""
}

Furthermore, the console.log statements are never called.

One would expect the second element of Items to be {"Name": "Green", "Count": 1 } (and console.log statements to be executed).

When Items is not nested, it works as expected - as you can see in this jsFiddle.

It is possible that I have overlooked something obvious, but in any case I would be grateful for insight and suggestions on how to work around this issue.

Upvotes: 1

Views: 1224

Answers (1)

Brian M. Hunt
Brian M. Hunt

Reputation: 83848

The answer seems to have been to make the array name's mapping top-level, like this:

var vm = ko.mapping.fromJS(data, {
        Items: {
            create: function(options) {
                options.data.Count = ++counter;
                console.log("Create:", options.data);
                return ko.mapping.fromJS(options.data);
            },
            update: function(options) {
                options.data.Count = ++counter;
                console.log("Update:", options.data);
                return ko.mapping.fromJS(options.data);
            }
        }
});

As per this jsFiddle.

I am still encountering an issue in code I have elsewhere, but evidently the problem illustrated above was not it.

Upvotes: 1

Related Questions