Reputation: 8416
From my server I receive an object that looks something like this:
var fromServer = {
foo: "Some foo",
barArray: [ "bar1", "bar2", "bar3", "bar4", "bar5" ]
};
Using the mapping plugin for knockout, I want to customize how the view model is constructed and break the array up into sub-arrays of length 2. Something like this:
viewModel: {
foo: "Some foo",
barArray: [ ["bar1", "bar2"], ["bar3", "bar4"], ["bar5"] ]
}
On my way there, I realized that that the create
callback is called once per array item. Here is my view:
<h1 data-bind="text: foo"></h1>
<ul data-bind="foreach: barArray">
<li data-bind="text: $data.name"></li>
</ul>
And the javascript:
var fromServer = { foo: "Some foo", barArray: [ "bar1", "bar2", "bar3", "bar4", "bar5" ] };
var mapping = {
'barArray': {
create: function(options) {
return new barModel("This is " + options.data);
}
}
};
var barModel = function(data) {
this.name = data;
};
var viewModel = ko.mapping.fromJS(fromServer, mapping);
ko.applyBindings(viewModel);
Here's a fiddle showing the behaviour
Here's the real question: Using the create
callback, can I access the whole array, rather than each element, one at at time? Or, am I approaching this in the wrong way?
Upvotes: 0
Views: 221
Reputation: 746
You can restructure your incoming array the way you would use it before creating your view model. Rather than using array of data that are 'sematically grouped' in some way, you can turn it into array of objects with properties filled accordingly.
I assume your data somehow related to weekdays, so I created WeekViewModel that will hold data for each week day. Before mapping data to viewmodel, I process if with ProcessBeforeCreatingViewModel function:
function WeekViewModel(data) {
var self = this;
ko.mapping.fromJS(data, {}, self);
}
function ProcessBeforeCreatingViewModel(data) {
var tempObj = null;
var data_processed = {
foo: data ? data.foo : '',
barArray: []
};
if (data && data.barArray) {
data.barArray.forEach(function (barItem, index) {
if (index % days.length == 0) {
tempObj = {};
days.forEach(function (dayName) {
tempObj[dayName] = undefined;
});
data_processed.barArray.push(tempObj);
}
tempObj[days[index]] = barItem;
});
}
return data_processed;
}
var mapping = {
'barArray': {
'create': function(options) {
return new WeekViewModel(options.data);
}
}
};
var fromServer_Processed = ProcessBeforeCreatingViewModel(fromServer);
var viewModel = ko.mapping.fromJS(fromServer_Processed, mapping);
ko.applyBindings(viewModel);
Here is a fiddle: http://jsfiddle.net/JeJKP/
Upvotes: 0
Reputation: 436
You need to do this, for mapping objects from the root of the JSON
var mapping = {
'': {
create: function(options) {
return new .....
}
}
};
Upvotes: 1
Reputation: 5147
Looking at the documentation, the options parameter passed into the create method has two properties:
data
: The JavaScript object containing the data for this child
parent
: The parent object or array to which this child belongs
so you can access it using options.parent
.
Upvotes: 0