web-dev-qa-db-fra.com

Le moyen le plus simple de réinitialiser le modèle Backbone aux valeurs par défaut initiales?

Mes modèles ont déjà un hash defaults. Lorsque certaines parties de la vue/page sont réinitialisées, je souhaite réinitialiser les modèles à leurs valeurs par défaut d'origine.

Actuellement, je règle explicitement chaque attribut à sa valeur par défaut. Existe-t-il un élément intégré ou une fonction JavaScript/Underscore.js/Backbone.js/jQuery que je pourrais utiliser pour le faire en une seule déclaration?

59
PhD
myModel.clear().set(myModel.defaults);
120
Peter Lyons

Je suis venu avec l'approche suivante:

reset: function () {
    this.clear({silent: true});
    this.set(this.defaults);
}

Avoir {silent: true} dans l'appel clear() garantit que l'événement change n'est pas déclenché; il ne sera déclenché que lors de l'appel set().

5
saabeilin

Je fais cela lorsque le modèle a des propriétés d'objet initial non nul.

d'abord, définissez par défaut en tant que fonction

var MyModel = Backbone.Model.extends({

    defaults:function(){

        return {
            AnArrayTypeProp:[]
        };
    }

});

deuxièmement, lorsque cela est nécessaire pour réinitialiser le modèle par défaut

model.clear().set(model.defaults());
5
codeboy

J'ai également pensé à utiliser model.clear() et model.set() conjointement. Ensuite, j'ai rencontré le problème suivant: je déclenche deux fois l'événement change . Utiliser l'option silent pour appeler model.clear() n'est pas une option, car je souhaite également qu'un événement change soit déclenché, lorsqu'une propriété n'est pas définie.

J'ai fini par ajouter une méthode model.reset(). Il utilise un nouvel hachage d'attributs et remplit ce hachage avec les valeurs undefined pour les anciennes clés d'attributs ne figurant pas dans le nouvel hachage d'attribut.

Model.prototype.reset = function(attrs, options) {
    for (var key in this.attributes) {
        if (key in attrs) continue;
        attrs[key] = void 0;
    }

    return this.set(attrs, options);
};

De cette façon, vous réinitialisez les anciens attributs du modèle et obtenez un événement change valide pour chaque attribut ancien et nouveau.

3
Johnny

Basé sur les réponses de saabeilin et la source annotée de Backbone , je suis arrivé avec une fonction optimale pour répondre au besoin de réinitialiser un modèle.

Réinitialisation réutilisable

/**
 * Clears the model's attributes and sets the default attributes.
 * @param  {Object} attrs to overwrite defaults
 * @param  {Object} options  to pass with the "set" call.
 * @return {Backbone.Model}  this object, to chain function calls.
 */
reset: function(attrs, options) {
    // adds default option reset to true
    options = _.extend({ reset: true }, options);

    // ensure default params
    var defaults = _.result(this, 'defaults');
    attrs = _.defaults(_.extend({}, defaults, attrs), defaults);

    // apply
    this.clear({ silent: true }).set(attrs, options);

    // triggers a custom event, namespaced to model in order
    // to avoid collision with collection's native reset event
    // when listening to a collection.
    if (!options.silent) this.trigger('model:reset', this, options);

    return this;
},

La ligne suivante garantit que même si un attribut est passé en tant que { test: undefined } non défini, il conservera sa valeur par défaut.

attrs = _.defaults(_.extend({}, defaults, attrs), defaults);

Voici un exemple:

var defaults = { test: 1 }, 
    attrs = { test: undefined };

_.extend({}, defaults, attrs);                       // {test: undefined}
_.defaults(_.extend({}, defaults, attrs), defaults); // {test: 1}

Extension du squelette

Et si vous le souhaitez avec tous les modèles Backbone, vous pouvez étendre Backbone lui-même:

_.extend(Backbone.Model.prototype, {
    reset: function(attributes, options){
        /* ... */
    }
});

Disclaimer: Ne faites pas cela si vous écrivez une librairie JavaScript ou un plugin Backbone, car cela pourrait entrer en collision avec une autre lib ou causer un comportement différent de celui attendu par la personne utilisant votre code.

3
Emile Bergeron

Qu'en est-il de remplacer la valeur du modèle actuel par un nouveau modèle vide:

myModel = new model(); // default values will be considered
1
ismnoiet

Ma solution est:

model.clear({silent: true}).set(model.defaults);
0
Daniel Ortegón