web-dev-qa-db-fra.com

Exclure les propriétés du modèle lors de la synchronisation (Backbone.js)

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)

43
Simon Boudrias

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.

47
Simon Boudrias

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);
    },
});
35
byoungb

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);
},
11
oak

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, ...

6
Pascal

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

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);
},
3
Ross Allen

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')
});
2
John Xiao

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.

2
rinat.io

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.

0
Pavel Sedek

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.

0
Tallmaris

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']
});
0
Gabriel Lupu