34 votes

Ajout de propriétés au modèle de vue créé à l'aide du plug-in de mappage Knockout JS

Je suis en train de travailler à travers la cartographie plugin exemple sur le Knockoutjs site web.

C'est l'exemple des données.

Knock-out JS Plugin de Cartographie

var data = {
    name: 'Scott',
    children: [
        { id : 1, name : 'Alice' }
    ]
}

L'exemple montre comment remplacer la cartographie pour l'un des enfants, mais comment puis-je modifier la cartographie de l'objet de base.

Si par exemple je voulais ajouter un "FavouriteChild" propriété de Scott comment m'y prendre?

Je suppose que j'ai besoin d'utiliser la fonction create sur la cartographie de base, mais je ne peux pas trouver un exemple de la syntaxe n'importe où.

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 : à Partir de la accepté de répondre ci-dessous, j'ai trouvé que cela fonctionne

<span data-bind='text: AdditionalProperty'>

Le knock-out de code

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);

24voto

RP Niemeyer Points 81663

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;
  }
};
 

13voto

jwize Points 823

Voici une suite à cette réponse sur la base de RP Niemeyer solution

Cette réponse est basée sur la solution ci-dessus et de son blog, Merci pour ça! J'ai pensé que je devrais ajouter quelques détails, car il répond à quand le tableau n'est pas un premier niveau d'objet.

 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 le premier niveau de l'objet et des enfants est sous la propriété de cette personne. La ligne viewModel.personne = ko.la cartographie.fromJS(viewModel.personne, cartographie) n'était pas intutive pour moi à la première.

Et ici, c'est une légère variation

La personne objet est une observable qui est ajouté ou mis à jour après il est créé à partir du serveur de données json.

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;
}

Certains de liaison de code dans le html

En fin de compte, vous aurez besoin de mettre pour l'utiliser à un certain point, comme ceci:

<div data-bind="foreach:viewModel.selectedPerson().children">
    <span data-bind="text:fullName"></span>
</div>

Merci pour votre aide! Je ne pouvais pas avoir fait cela loin sans votre blog.

3voto

Jason Points 31

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);
  }
};
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X