Knockoutjs: ajout de propriétés et de fonctions observables aux objets dans une cartographie générée par observable

StackOverflow https://stackoverflow.com/questions/8401799

Question

Je suis nouvelle Knockoutjs, et je suis coincé en essayant d'ajouter des propriétés et des méthodes supplémentaires aux objets générés dans le ko.observableArray() comme créé par le mapping brancher.


Voici où je vais:

  • J'ai une gamme JSON de Users
  • J'ai créé le ko.observableArray() avec le plugin de cartographie
  • J'ai un modèle qui crée une ligne de table pour chaque User, jusqu'ici tout va bien: o)


Voici ce que j'essaie de faire:

Chaque User a une propriété appelée 'IsActive' - Je voudrais data-bind un événement de clic sur une méthode sur chaque User objet qui bascule ceci 'IsActive' propriété.

Cette question semblait prometteuse, mais cela me semble être une duplication inutile de devoir déclarer le modèle de vue entier dans JS (à moins que ce ne soit ainsi que je dois le faire!) - Est-il possible d'étendre l'objet généré?

Je pensais plus dans ce sens, où il existe un moyen de déclarer des propriétés ou des méthodes supplémentaires, et leur faire étendre le mapping objets générés, mais cet article concerne les objets uniques plutôt que d'extenser des objets dans un tableau généré.


Voici le code: http://jsfiddle.net/yzksf/2/ (Ne fonctionnant pas encore dans JS Fiddle - mais je continuerai à jouer avec et à mettre à jour ce lien lorsque je le ferai fonctionner).

Merci de votre aide

Était-ce utile?

La solution

Il existe plusieurs options que vous pourriez considérer.

-Un est d'utiliser le create rappeler Pour contrôler la façon dont vos objets "utilisateur" sont créés. Vous pouvez soit définir les observables vous-même et ajouter des fonctionnalités supplémentaires, soit appeler le plugin de mappage sur l'objet utilisateur individuel, puis ajouter des fonctionnalités supplémentaires.

Serait quelque chose comme: http://jsfiddle.net/rniemeyer/fkvak/

-Lu encore, vous pouvez placer la fonction "Toggle" sur votre vue ViewModel, puis y transmettre l'objet "utilisateur".

Une belle façon avec 1,3, c'est utiliser ko.dataFor Parallèlement à quelque chose comme la fonctionnalité en direct / déléguée / sur la délégation des événements de JQuery. Serait comme: http://jsfiddle.net/rniemeyer/fkjnr/

//unobtrusive event handler
$(".toggle").live("click", function() {
    var user = ko.dataFor(this);
    if (user) {
       viewModel.toggleIsActive(user);
    }
});

Si vous ne souhaitez pas utiliser la délégation d'événements, vous pouvez passer l'élément directement à l'aide d'une fonction anonyme comme: http://jsfiddle.net/rniemeyer/gpqtn/

EDIT: à partir de 2.0, les données actuelles sont automatiquement transmises au gestionnaire lors de l'utilisation de liaisons de clic / événement, vous pouvez donc simplement faire:

<a href="#" data-bind="click: $root.toggleIsActive"><span data-bind="text: IsActive"></span></a>

Autres conseils

C'est ce que j'ai trouvé en utilisant les réponses de vos et de Ryan ... semble fonctionner. Veuillez laisser les commentaires, car je suis nouveau à Knockout et moi moi-même, si c'est une bonne approche.

JS:

$(function() {
    $.get("users/getUsers", function(r){
        var vm = ko.mapping.fromJS(r, {
            users: {
                create: function(user){
                    var methods = {
                        toggleIsActive: function(u){u.IsActive(!u.IsActive());},
                        foo: function(u){console.log(u);},
                        bar: function(u){/*whatever*/},   
                    }
                    return $.extend(ko.mapping.fromJS(user.data), methods);
                }
            }
        });
        ko.applyBindings(vm);
    }, 'json');
});

DOM:

<!-- ko foreach: users -->
   <a href="#" data-bind="click: toggleIsActive"><span data-bind="text: IsActive"></span></a>
<!-- /ko -->

J'ai trouvé un moyen de le faire, mais cela signifie faire une boucle à travers les objets générés dans le tableau une fois qu'ils ont été créés. Je préférerais un moyen d'obtenir le même résultat sans la boucle supplémentaire.

ÉDITER: Comme RP Niemeyer le suggère dans sa réponse! ; o)

Quoi qu'il en soit, une façon d'ajouter des propriétés à un objet existant est d'utiliser jQuery Extend () pour combiner les objets.

Tout d'abord, déclarez les propriétés et fonctions supplémentaires dans un nouvel objet:

var userModel = {
    toggleIsActive: function() {
        console.log('toggleIsActive called: before: ' + this.IsActive());
        this.IsActive(!this.IsActive());
        // todo: save!
        console.log('toggleIsActive called: after: ' + this.IsActive());
    }
}

Ensuite, après le ko.mapping.fromJS() appel, Mais avant le ko.applyBindings() appel, faire une boucle à travers les objets dans le tableau généré et les étendre:

viewModel.users = ko.mapping.fromJSON(/* get JSON */);

for (var i = 0; i < viewModel.users().length; i++) {
    $.extend(viewModel.users()[i], userModel);
}

ko.applyBindings(viewModel);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top