ko.mapping create function, extend object
Asked Answered
B

1

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);
Barkeeper answered 20/3, 2012 at 0:40 Comment(0)
B
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);
Bullen answered 20/3, 2012 at 4:5 Comment(12)
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 :).Barkeeper
Maybe the key becomes data.id? In debugging my solution it looks like that might be the case.Barkeeper
In this case, the key function returns data.id. Does that help?Bullen
so, knockout recognizes "key" as a function which defines if the element of data.id is unique?Barkeeper
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.Bullen
OK, that's how I understood it. Really great help! Thanks again! You've gotten me out of 10 binds just this week :).Barkeeper
So, in this instance, what is the point in using the mapping plugin? You're doing everything manually anyway, aren't you?Airspace
Is it possible to use this technique to plug-in dirty flags on individual properties using libs like knockout.dirtyFlag? github.com/CodeSeven/KoLite/blob/master/knockout.dirtyFlag.jsRumery
I'm with @TomMcKearney I don't understand what the gain is from the mapping plugin if you're creating a Person object manually.??Bargain
@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.Bullen
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.Freightage
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 computedFreightage

© 2022 - 2024 — McMap. All rights reserved.