web-dev-qa-db-fra.com

backbone.js utilise différentes URL pour enregistrer et récupérer le modèle

Mon back-end a deux pages distinctes, une pour gérer la demande de sauvegarde du modèle et l'autre pour la récupération du modèle.

Quelle est la meilleure approche pour appeler save () et fetch () pour utiliser différentes URL? Merci.

Edit: Après avoir étudié la source annotée, je vois que l'on peut réellement fournir un hachage options à fetch et enregistrer

//taken from backbone source:
save : function(attrs, options) {
  options || (options = {});
  if (attrs && !this.set(attrs, options)) return false;
  var model = this;
  var success = options.success;
  options.success = function(resp, status, xhr) {
    if (!model.set(model.parse(resp, xhr), options)) return false;
    if (success) success(model, resp, xhr);
  };
  options.error = wrapError(options.error, model, options);
  var method = this.isNew() ? 'create' : 'update';
  return (this.sync || Backbone.sync).call(this, method, this, options);
},

Dans la sauvegarde, à quoi sert le attrs? Je viens d'appeler myModel.save () sans rien transmettre et cela a toujours haché correctement les attributs de mon modèle. Mais maintenant que je veux fournir une "URL de sauvegarde" et je suis tenté d'appeler

myModel.save(undefined, {
    url: 'myPath'
})

avec l'indéfini requis pour 'ignorer' le premier paramètre attrs.

38
fortuneRice

Si vous lisez la source, vous avez probablement déjà une solution de travail. Vous avez essentiellement deux options (probablement plus) -

  1. Passer l'URL dans save ()/fetch ()

save () prend deux paramètres attr et options attr - est un hachage des attributs de modèle et est utilisé pour mettre à jour le modèle avant de sauvegarder. par exemple.

myModel.save(attrs)

est équivalent à

myModel.set(attrs)
myModel.save()

Le deuxième paramètre est un hachage d'options, qui est transmis à this.sync () (puis Backbone.sync puis $ .ajax) - la définition de l'url dans ce hachage fonctionnera comme prévu. Vous pouvez passer false, indéfini ou {} comme premier paramètre pour ignorer la mise à jour.

  1. Remplacer Backbone.sync

Plutôt que d'avoir des URL dispersées dans votre code à chaque fois que vous appelez save () ou fetch (), écrivez votre propre fonction de synchronisation pour calculer l'url pour vous, le délégué au Backbone.sync d'origine pour faire le gros du travail

par exemple. (Cette fonction de synchronisation ajoute/sauvegarde à l'URL sur les actions CREATE, UPDATE et DELETE)

function mySyncFunction(method, model, options){
  if(method=='GET'){
    options.url = model.url; 
  }else{
     options.url = model.url + '/save'; 
  }
  return Backbone.sync(method, model, options);
}

Pour utiliser votre méthode de synchronisation personnalisée, déclarez-la simplement comme faisant partie de votre modèle

var myModel = Backbone.Model.extend({ 
  ...

  "sync": mySyncFunction,

  ...
});
72
gingerhendrix

La réponse de Gingerhendrix couvre les bases, mais j'ai pensé qu'il valait la peine d'élaborer sur la méthode pour passer une valeur d'options pour save/delete/fetch.

Au lieu de salir votre code avec des URL à chaque endroit que vous appelez l'une de ces méthodes, vous pouvez également remplacer la méthode sur votre modèle, puis déléguer à l'original Backbone.Model méthode comme celle-ci:

var MyModel = Backbone.Model.extend({
  save: function(attributes, options) {
    options = _.defaults((options || {}), {url: "http://your.save.url.com/"});
    return Backbone.Model.prototype.save.call(this, attributes, options);
  },
  // same thing for fetch and delete to give them different urls...
}

Ensuite, vous pouvez appeler la méthode dans votre code sans avoir à vous soucier de vous souvenir de définir url dans les options.

24
Ted Naleid

Je veux clearifier la réponse de @gingerhendrix: vous pouvez passer l'url à des options dans save et cela ira directement à la requête xhr (ce n'est pas évident de la documentation ou du code source ou de la réponse donc je poste ot comme réponse séparée):

model.save({}, {url: '/custom-url'});
9

Si vous avez un modèle et une collection comme: -

MyModel = Backbone.Model.extend({

url: function(){ "API/"
      return "API/MyModel/" +this.get("id");
    }
});

MyCollection = Backbone.Collection.extend({
    model: MyModel ,
    url: "API/MyModels"
});

pour récupérer la collection, il suffit d'appeler

MyCollection.fetch({
       success: function(){
       //do something here
       },
       error: function(){
       //Handle your error
       }
});

Pour enregistrer votre modèle en supposant que vous avez l'ID du modèle et que vous avez instancié votre collection (en l'appelant myCollection).

var model = myCollection .get(id);
   model.save(
                             model.attributes,
                                {
                                    success: function (model, response) {

                                        //do something on success
                                    },
                                    error: function (model, response) {
                                       //handle the error
                                    }
                                }
                            );
2
MikeRay1