6

Is it possible to modify the (for lack of a better term) schema of an object during the mapping process? I would imagine it is, I just can't seem to get it to work. I'm trying something like this:

var data = {
    itemOne: 'someData',
    itemTwo: 'moreData'
}

var mapping = {
    "newItem": {
          create: function(options) {
            return ko.observable(false);
          }
    }
};

ko.mapping.fromJS(data, mapping, _model.observableArrayPart);
farina
  • 3,486
  • 6
  • 32
  • 44

1 Answers1

15

Here is a sample that shows customizing how your array is creating and defining a key for it, so that you can apply updates using the mapping plugin: http://jsfiddle.net/rniemeyer/LHeQZ/

var data = [
    { id: 1, first: "Bob", last: "Smith" },
    { id: 2, first: "Jim", last: "Jones" },
    { id: 3, first: "Delete", last: "Me" }
];

var updatedData = [
    { id: 1, first: "Robert", last: "Smith" },
    { id: 2, first: "James", last: "Jones" },
    { id: 4, first: "New", last: "Guy" }
];

var Person = function(data) {
    this.id = data.id;
    this.first = ko.observable(data.first);
    this.last = ko.observable(data.last);
    this.full = ko.computed(function() {
        return this.first() + " " + this.last();
    }, this);        
};


var dataMappingOptions = {
    key: function(data) {
        return data.id;        
    },
    create: function(options) {
        return new Person(options.data);
    }        
};


var viewModel = {
    people: ko.mapping.fromJS([]),
    loadInitialData: function() {
        ko.mapping.fromJS(data, dataMappingOptions, viewModel.people);        
    },
    loadUpdatedData: function() {
        ko.mapping.fromJS(updatedData, dataMappingOptions, viewModel.people);  
    }        
};

ko.applyBindings(viewModel);
RP Niemeyer
  • 114,592
  • 18
  • 291
  • 211
  • So, in this example you are saying the key is all of data? I thought you had to pass in some "item" to do this. This is really impressive stuff, I didn't picture laying it out like this. They need an example like this on the site, or you should add one to KnockMeOut :). – farina Mar 20 '12 at 17:22
  • Maybe the key becomes data.id? In debugging my solution it looks like that might be the case. – farina Mar 20 '12 at 17:36
  • In this case, the `key` function returns `data.id`. Does that help? – RP Niemeyer Mar 20 '12 at 20:04
  • so, knockout recognizes "key" as a function which defines if the element of data.id is unique? – farina Mar 20 '12 at 21:37
  • 1
    the mapping plugin lets you pass in mapping options. The `key` and `create` functions are part of that. Normally, you would specify `key` and `create` functions for some property in your data like `items`, but in this case we are just configuring them at the root level, because we are dealing directly with an array of data. – RP Niemeyer Mar 20 '12 at 21:39
  • 1
    OK, that's how I understood it. Really great help! Thanks again! You've gotten me out of 10 binds just this week :). – farina Mar 20 '12 at 21:46
  • 1
    So, in this instance, what is the point in using the mapping plugin? You're doing everything manually anyway, aren't you? – Tom McKearney Jul 05 '13 at 20:33
  • Is it possible to use this technique to plug-in dirty flags on individual properties using libs like knockout.dirtyFlag? https://github.com/CodeSeven/KoLite/blob/master/knockout.dirtyFlag.js – Mr. Young Aug 20 '13 at 18:30
  • I'm with @TomMcKearney I don't understand what the gain is from the mapping plugin if you're creating a Person object manually.?? – Brad Bamford Nov 12 '13 at 18:00
  • @BradBamford - in this scenario the mapping plugin does still handle the updates for you. I personally don't use the mapping plugin, so otherwise I agree with you. I like to have more control over how everything is created. – RP Niemeyer Nov 12 '13 at 18:30
  • I have an issue where an observable in the Person object, for example, has a rateLimit extension. When the mapping fromJS creates an object this way, the rateLimit does not work. – Ian May 31 '16 at 10:58
  • So it seems that an object created via the mapping fromJS has an issue when there's an extended computed property with a rateLimit. The rateLimit wasn't working. I managed to make do by subscribing, rather than using a ko computed – Ian May 31 '16 at 15:03