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?
myModel.clear().set(myModel.defaults);
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()
.
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());
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.
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.
/**
* 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}
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.
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
Ma solution est:
model.clear({silent: true}).set(model.defaults);