Kyle
Kyle

Reputation: 4376

Add computed for each object in mapping

I have the following view model in my application:

var DashboardVM = function (serverData) {
    var self = this;
    self.tiles = ko.mapping.fromJS(serverData);
    self.someotherproperties
    ...
};
var tileData = @Html.Raw(Json.Encode(Model.Tiles));
var dashboardVM = new DashboardVM(tileData);
ko.applyBindings(dashboardVM);

I'd like to add a ko.computed function for each item in self.tiles. I've seen some examples online that suggest that it's possible, but I can't quite figure out the correct syntax to do this.

Upvotes: 1

Views: 198

Answers (2)

PatrickSteele
PatrickSteele

Reputation: 14687

From looking at the docs, you should be able to pass some mapping options to the mapping plugin to customize the creation of the tiles item. Without knowing more about your data structure it's hard to give a sample, but this might work for you:

var mapping = {
    'tiles' : {
        create: function(options) {
            return new specialTiles(options.data);
        }
    }
}

var specialTiles = function(data) {
    ko.mapping.fromJS(data, {}, this);

    this.tileSize = ko.computed(function() {
        return this.tileLength * 2;
    }, this);
}

Now when you do your mapping, pass the mapping options:

ko.mapping.fromJS(serverData, mapping, this.tiles);

Upvotes: 3

Damien
Damien

Reputation: 8987

If serverData is an array you could do that. As you can see I added a computed property named comp which returns a text based the title property.

var DashboardVM = function (serverData) {
    var self = this;
    self.titles = ko.mapping.fromJS(serverData);
    for(var index =  0; index<self.titles().length; index++) {
        var item = self.titles()[index];
        item.comp = ko.computed(function(){
            return 'new' +item.title()
        });
    }
};
//var tileData = @Html.Raw(Json.Encode(Model.Tiles));
var titleData = [{title :'t1'}, {title :'t2'}, {title :'t3'}]
var dashboardVM = new DashboardVM(titleData);
ko.applyBindings(dashboardVM);


<div data-bind="foreach:titles">
    <span data-bind="text:title">
    </span>    
    <span data-bind="text:comp">
    </span>
    <br/>
</div>

See fiddle

I hope it helps.

Upvotes: 1

Related Questions