knockout mapping with computed fields
Asked Answered
O

3

5

I'm getting data from a WCF service,and i map, and bind the data with my DOM object :

var PayinyVM = {};

    $.getJSON('/service/PaidService.svc/PaidList', function (data) {
        var tmp = JSON.stringify(data.d);

        PayinyVM.model = ko.mapping.fromJSON(tmp);
        ko.applyBindings(PayinyVM);
    }); 

the result is shown as excepted on my DOM bind it to model. What I couldn't find out is how to add some computed observable let's say my data is returning people with FirstName and LastName, how can I make a computed observable FullName with FN + ' ' + LN.

Overvalue answered 5/6, 2012 at 23:11 Comment(0)
A
10

Here's a working copy of your fiddle, I had to make a lot of assumptions as your fiddle wasn't even correct javascript and seemed quite confused and didn't even reference knockout

var PaidPeople = function(data) {
    var self = this;
    ko.mapping.fromJS(data, {}, this);
    this.fullName = ko.computed(function () {
                    return self.Name() + " : just ";
                });
}

var PayinyVM = function (data) {
                var self = this;

                ko.mapping.fromJS(data, {
                    'model' : {
                        create: function(options) {
                            return new PaidPeople(options.data);
                    }                        
                  }
                }, self);                
            };

var data = {model:[{__type: "PaidPeople:#model", Amount:110, Attendee:1, Name:'John'}]};

ko.applyBindings(new PayinyVM(data)); ​

and a fiddle that works : http://jsfiddle.net/qeUHd/

Ari answered 6/6, 2012 at 1:15 Comment(6)
I had tried it before, and get PayinyVM.Name is not a function. In my program actually i'm trying to add something to Name. Thanks anyway. there is version in jsfiddle.net/nYF67Overvalue
well, you weren't showing that code...update your question to show that.Ari
Which code? it's madcapnmckay answer. Basically I'd like to know once you map viewmodel to a data received how to add some computed fields base to it. ThanksOvervalue
Keith what's wrong with it. that's why i put it fiddle in order for people who know knockout to correct it. Thanks anywayOvervalue
your fiddle wasn't correct javascript, and didn't even have any references to the knockout library.Ari
Thanks keith, now i have to go through your code to understand.Overvalue
S
4

You can invert the mapping by creating a model object that is mapped internally.

var PayinyVM = function (data) {
    var self = this;
    ko.mapping.fromJS(data, {}, self);
    this.fullName = ko.computed(function () {
        return self.Name() + " : just ";
    });
};

$.getJSON('/service/PaidService.svc/PaidList', function (data) {    
    ko.applyBindings(new PayinyVM(data.d));
});

Hope this helps.

Snorkel answered 5/6, 2012 at 23:20 Comment(7)
Thank yo very much for your help, but it doesn't work for me. I changed MyModel to PayingVM, and parse(data) to parse(tmp) still i'm getting error ; "self.FirstName is not a function inside of the computed function. Any other correction. Here is my new CodeOvervalue
var PayinyVM = function (data) { var self = this; ko.mapping.fromJS(data, {}, self); this.fullName = ko.computed(function () { return self.Name() + " : just "; }); }; $.getJSON('/service/PaidService.svc/PaidList', function (data) { var tmp = JSON.stringify(data.d); PayinyVM.model = new PayinyVM(JSON.parse(tmp)); // ko.mapping.fromJSON(tmp); ko.applyBindings(PayinyVM); });Overvalue
@FrenchiInLA - You were new'ing up the model correctly but then assigning it to a property of the PayinyVM function which doesn't make sense. Also there is no need to stringify your json first, it's already a json object why serialize. I've edited the code to fit what you have.Snorkel
Thanks again madcap. It makes sense, and i start understanding knockout, but still getting the self.Name is not a function. the data passed is correct,and Name is part of each object of the data, but self is somehow not mapped to this data I will try to make a simple mock file in js,and will let youknow. thanks again, and I really appreciated your helpOvervalue
jsfiddle.net/nYF67 i just added data the way that i get from WCF.Please take a look at it and let me know what i'm missing. ThanksOvervalue
Few issues with your fiddle. The data is not valid json. Pass it to JSONLint and see. Missing knockout in the resources. You were foreaching on a model property that doesn't exist. Here's how it should be. jsfiddle.net/madcapnmckay/nWTMf/3 If you are expecting an array of objects then it should be received as { arrayName: [ .. ] }, then your foreach would be on arrayName.Snorkel
Also if you want to deal with arrays of objects you should read the docs on the mapping plugin options. You will need a second model object e.g PersonVM.Snorkel
G
2

Turns out I have to define all view model properties inside javascript so that knockout can initialize the view model with properties, before I update it with server data

Reference: http://www.underwatergorilladome.com/how-to-use-knockouts-computed-observables-with-the-mapping-plugin/

http://jsfiddle.net/GLDxx/2/

var model = {
    username : ko.observable(),
    get_student_info : ko.mapping.fromJS(
        {
            usr_lname : null,
            usr_fname : null,
            gender : null,
            dob : null
        },
        {
            create: function(options) {
                return (new (function () {
                    this.name = ko.computed(function () {
                        if (this.usr_lname == undefined || this.usr_fname == undefined)
                            return null;
                        else
                            return this.usr_lname() + ' ' + this.usr_fname(); 
                    }, this);

                    // let the ko mapping plugin continue to map out this object, so the rest of it will be observable
                    ko.mapping.fromJS(options.data, {}, this);
                }));
            }
        }
    )
};
Gabelle answered 20/3, 2014 at 4:33 Comment(1)
Having spent an hour searching for the answer, this example made everything clear and I now have what I want working :)Chimb

© 2022 - 2024 — McMap. All rights reserved.