Je travaille sur l'exemple du plugin de cartographie sur le site Web de Knockoutjs.
Ce sont les données d'exemple.
var data = {
name: 'Scott',
children: [
{ id : 1, name : 'Alice' }
]
}
L'exemple montre comment remplacer le mappage pour l'un des enfants, mais comment puis-je modifier le mappage de l'objet de base.
Si, par exemple, je voulais ajouter une propriété "FavouriteChild" à Scott, comment procéder?
Je suppose que je dois utiliser la fonction create sur le mappage de base mais je ne trouve nulle part d'exemple de syntaxe.
var myChildModel = function(data) {
ko.mapping.fromJS(data, {}, this);
this.nameLength = ko.computed(function() {
return this.name().length;
}, this);
}
var mapping = {
'children': {
create: function(options) {
return new myChildModel(options.data);
}
}
}
var viewModel = ko.mapping.fromJS(data, mapping);
EDIT: D'après la réponse acceptée ci-dessous, j'ai trouvé que cela fonctionnait
<span data-bind='text: AdditionalProperty'>
Le code KO
var mapping = {
create: function (options) {
//customize at the root level.
var innerModel = ko.mapping.fromJS(options.data);
innerModel.AdditionalProperty = 'Hello World';
return innerModel;
}
}
var viewModel = ko.mapping.fromJS(data, mapping);
//use this as our model bindings
ko.applyBindings(viewModel);
Vous devez utiliser une méthode create
sur l'objet de mappage lui-même comme:
var mapping = {
//customize at the root level.
create: function(options) {
//first map the vm like normal
var vm = ko.mapping.fromJS(options.data);
//now manipulate the returned vm in any way that you like
vm.someProperty = "test";
vm.someComputed = ko.computed(function() {
return vm.first() + " " + vm.last();
});
//return our vm that has been mapped and tweaked
return vm;
}
};
Voici une suite à cette réponse basée sur la solution de RP Niemeyer
Cette réponse est basée sur la solution ci-dessus et sur son blog - Merci pour ça! J'ai pensé que je devrais ajouter quelques détails car il traite lorsque le tableau n'est pas un objet de premier niveau.
var data = {
person: {
children: [{ id: 1, firstName: 'Scot', lastName: 'Weise'}]
}
};
var mapping = {
'children': {
create: function(options) {
return (new (function() {
// setup the computed binding for some reason I had
// to use ko.dependentObservable instead of ko.computed
// or errors showed up.
this.fullName = ko.dependentObservable(function() {
return this.firstName() + ' ' + this.lastName();
}, this);
ko.mapping.fromJS(options.data, { }, this);
})(/* call the ctor here */));
}
}
};
// Create view model and map the data object to the model.
var viewModel = ko.mapping.fromJS(data, {});
// update the viewModel with the mapping object that contains
// some a computed property(s)
viewModel.person = ko.mapping.fromJS(viewModel.person, mapping);
ko.applyBindings(viewModel);
Notez que la personne est l'objet de premier niveau et que les enfants sont une sous-propriété de cette personne. La ligne viewModel.person = ko.mapping.fromJS (viewModel.person, mapping) ne m'était pas intuitive au début.
Et voici une légère variation
L'objet personne est un observable qui est ajouté ou mis à jour après sa création d'origine à partir des données json du serveur.
var viewModel = {};
$(document).ready(function () {
var person = getPerson();
// selected person is added to the viewModel
viewModel.selectedPerson = ko.observable(person);
ko.applyBindings(viewModel);
});
function getPerson() {
// you would probably pass this into the function as a parameter.
var person =
{
name: 'jim',
children: [{ id: 1, firstName: 'jane', lastName: 'bob'}]
};
var mapping = {
'children': {
create: function (options) {
return (new (function () {
// setup the computed binding
this.fullName = ko.dependentObservable(function () {
return this.firstName() + ' ' + this.lastName();
}, this);
ko.mapping.fromJS(options.data, {}, this);
})(/* call the ctor here */));
}
}
};
var result = ko.mapping.fromJS(person, mapping);
return result;
}
n code de liaison dans le html
En fin de compte, vous devrez le mettre à profit à un moment comme celui-ci:
<div data-bind="foreach:viewModel.selectedPerson().children">
<span data-bind="text:fullName"></span>
</div>
Merci pour votre aide! Je n'aurais pas pu arriver aussi loin sans votre blog.
Notez que pour définir des observables calculés supplémentaires sur un enfant, vous devrez passer un autre ensemble d'options de mappage
var mapping = {
create: function(options) {
//customize at the root level.
var mapping2 = {
'children': {
create: function(options) {
//customize children also
}
}
}
//call ko.mapping.fromJS on the options.data as well with further customization
ko.mapping.fromJS(options.data, mapping2, this);
}
};
Un autre exemple basé sur les exemples fournis par Jason et RP Niemeyer.
data
est ce que nous obtenons après une requête ajax, sur laquelle nous ajoutons deux observables imbriquées (viewModel.weekly.selectedWeek
et viewModel.monthly.selectedMonth
):
var data = {
"date": "2017-03-28",
"weekly": {
"weeks": [
{
"id": "201701",
"label": "Week 1"
},
{
"id": "201702",
"label": "Week 2"
}
]
},
"monthly": {
"months": [
{
"id": "201701",
"label": "01/2017"
},
{
"id": "201702",
"label": "02/2017"
}
]
}
}
var viewModelMapping = {
create: function (options) {
return (new (function () {
// viewModel root level
var mapping2 = {
'weekly': {
create: function (options) {
// viewModel.weekly
return new function () {
var model = ko.mapping.fromJS(options.data, {}, this);
model.selectedWeek = ko.observable();
return model;
};
}
},
'monthly': {
create: function (options) {
// viewModel.monthly
return new function () {
var model = ko.mapping.fromJS(options.data, {}, this);
model.selectedMonth = ko.observable();
return model;
};
}
}
};
ko.mapping.fromJS(options.data, mapping2, this);
})());
}
};
var viewModel = ko.mapping.fromJS(data, viewModelMapping);
ko.applyBindings(viewModel);