Existe-t-il un moyen d'exclure certaines propriétés de mon modèle lors de la synchronisation?
Par exemple, je garde dans mon modèle des informations sur un état d'affichage. Disons que j'ai un module de sélection et que ce module bascule simplement les attributs selected
sur mon modèle. Plus tard, lorsque j'appelle .save()
sur ma collection, je voudrais ignorer la valeur de selected
et l'exclure de la synchronisation avec le serveur.
Existe-t-il une manière propre de le faire?
(Faites-moi savoir si vous souhaitez plus de détails)
Cela semble être la meilleure solution (basée sur la question référencée @nikoshr)
Backbone.Model.extend({
// Overwrite save function
save: function(attrs, options) {
options || (options = {});
attrs || (attrs = _.clone(this.attributes));
// Filter the data to send to the server
delete attrs.selected;
delete attrs.dontSync;
options.data = JSON.stringify(attrs);
// Proxy the call to the original save function
return Backbone.Model.prototype.save.call(this, attrs, options);
}
});
Nous remplaçons donc la fonction de sauvegarde sur l'instance de modèle, mais nous filtrons simplement les données dont nous n'avons pas besoin, puis nous les procurons à la fonction prototype parente.
Dans Underscore 1.3.3, ils ont ajouté pick et dans 1.4.0, ils ont ajouté omit qui peut être utilisé très simplement pour remplacer la fonction toJSON
de votre modèle pour ajouter des attributs à la liste blanche. avec _.pick
ou des attributs de liste noire avec _.omit
.
Et puisque toJSON
est utilisé par la commande sync pour transmettre les données au serveur, je pense que c'est une bonne solution tant que vous ne voulez pas ces champs partout où vous utilisez toJSON
.
Backbone.Model.extend({
blacklist: ['selected',],
toJSON: function(options) {
return _.omit(this.attributes, this.blacklist);
},
});
ma solution combine tout ce qui précède. il suffit d'utiliser une liste blanche au lieu d'une noire .. c'est une bonne règle en général
définir
attrWhiteList:['id','biography','status'],
puis écraser la sauvegarde
save: function(attrs, options) {
options || (options = {});
//here is whitelist or all
if (this.attrWhiteList != null )
// Filter the data to send to the server
whitelisted = _.pick(this.attributes, this.attrWhiteList);
else
whitelisted =this.attributes;
/* it seems that if you override save you lose some headers and the ajax call changes*/
// get data
options.data = JSON.stringify(whitelisted);
if ((this.get('id') == 0) || (this.get('id') == null))
options.type = "POST"
else
options.type = "PUT";
options.contentType = "application/json";
// options.headers = {
// 'Accept': 'application/json',
// 'Content-Type': 'application/json'
// },
// Proxy the call to the original save function
return Backbone.Model.prototype.save.call(this, attrs, options);
},
En fait, il existe un moyen beaucoup plus simple d'y parvenir sans jouer avec la fonction de sauvegarde ou de synchronisation de la dorsale, car vous ne vous attendriez pas à ce que ce comportement soit permanent
si vous regardez la ligne 1145 de backbone.js, vous verrez que
// Ensure that we have the appropriate request data.
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
params.contentType = 'application/json';
params.data = JSON.stringify(options.attrs || model.toJSON(options));
}
Ce qui signifie que vous pouvez remplacer la partie données de la xhr en mettant des données dans vos options
Étant donné que la sauvegarde de la dorsale nécessite model.save ([attributs], [options])
Mais rappelez-vous que des attributs comme id peuvent être essentiels à une bonne sauvegarde
Exemple
model.save( {}, { data: JSON.stringify(data) } ) ;
Vous devriez donc faire quelque chose comme ça
var data = { id : model.id , otherAttributes : 'value' } ;
model.save( {}, { data : JSON.stringify(data) } );
Cela fait très bien l'affaire pour moi et pourrait être utilisé avec n'importe quel squelette avec xhr tel que chercher, enregistrer, supprimer, ...
J'ai trouvé quelques problèmes avec la solution acceptée, car options.data modifie la façon dont Backbone effectue les appels. Mieux utiliser options.attrs comme ceci:
Backbone.Model.extend({
save: function (attrs, options) {
options = options || {};
attrs = _.extend({}, _.clone(this.attributes), attrs);
// Filter the data to send to the server
delete attrs.selected;
options.attrs = attrs;
// Proxy the call to the original save function
return Backbone.Model.prototype.save.call(this, attrs, options);
}
});
Sur la base de plusieurs réponses, cela représente des cas d'objets nuls et un conditionnel dans Backbone qui n'envoie pas le contentType
if options.data
est déjà défini:
EDITABLE_ATTRIBUTES = ["name", "birthdate", "favoriteFood"];
...
save: function(attrs, options) {
// `options` is an optional argument but is always needed here
options || (options = {});
var allAttrs = _.extend({}, this.attributes, attrs);
var allowedAttrs = _.pick(allAttrs, EDITABLE_ATTRIBUTES);
// If `options.data` is set, Backbone does not attempt to infer the content
// type and leaves it null. Set it explicitly as `application/json`.
options.contentType = "application/json";
options.data = JSON.stringify(allowedAttrs);
return Backbone.Model.prototype.save.call(
this, allowedAttrs, options);
},
Définir options.attrs vous permettra de personnaliser les paramètres de l'API:
var model = new Backbone.Model();
model.save(null, {
wait: true,
success: function() {
},
attrs: _.omit(model.attributes, 'selected')
});
Puisque save
utilise toJSON
, nous le remplaçons:
toJSON: function(options) {
var attr = _.clone(this.attributes);
delete attr.selected;
return attr;
},
Mais cela peut ne pas fonctionner si vous utilisez toJSON et avez besoin de selected
dans les vues par exemple. Sinon, vous devrez probablement remplacer la méthode save
.
Pour définir uniquement les valeurs souhaitées, utilisez HTTP PATCH à la place de HTTP POST. Du côté de la dorsale, ajoutez simplement un attribut de patch à la méthode de sauvegarde:
entity.save(data,{patch:true})
En utilisant save avec cet attribut, seuls les champs passés en tant que data
sont envoyés au serveur.
S'il s'agit d'une occasion unique, vous pouvez utiliser mode.unset('selected', { silent:true })
(le silence est défini uniquement pour éviter de déclencher l'événement change), pour supprimer l'attribut ... Cela a le contre-effet pas si agréable d'avoir pour le réinitialiser après avoir enregistré cependant.
Cela dit, j'approuve totalement l'une des solutions ci-dessus. De plus, si c'est quelque chose dont vous avez besoin sur une base plus régulière.
Ayant ce même problème, j'ai décidé de créer un petit module qui peut aider: https://github.com/lupugabriel1/backbone-model-save
Voici comment vous pouvez l'utiliser dans vos modèles:
var myModel = new Backbone.ModelSave.extend({
notSync: ['name', 'age']
});