"Как" сохранить всю коллекцию в Backbone.js-позвоночник.синхронизация или jQuery."Аякс"?



Я хорошо знаю, что это можно сделать, и я посмотрел на довольно много мест (в том числе:Лучшая практика для сохранения всей коллекции?). Но мне все еще не ясно, "как именно" это написано в коде? (сообщение объясняет это на английском языке. Было бы здорово иметь конкретное объяснение javascript :)



говорят, у меня есть коллекция моделей - сами модели могут иметь вложенные коллекции. Я переопределил метод toJSON() родительской коллекции, и я получаю действительный объект JSON. Я хочу "сохранить" всю коллекцию (соответствующий JSON), но backbone, похоже, не встроен в эту функциональность.



var MyCollection = Backbone.Collection.extend({
model:MyModel,

//something to save?
save: function() {
//what to write here?
}

});


Я знаю, что где-то вы должны сказать:



Backbone.sync = function(method, model, options){
/*
* What goes in here?? If at all anything needs to be done?
* Where to declare this in the program? And how is it called?
*/
}


после того, как "просмотр" будет выполнен с обработкой, он отвечает за то, чтобы сообщить коллекции "сохранить" себя на сервере (способный обрабатывать запрос на массовое обновление/создание).



вопросы:




  1. как / в чем писать код, чтобы "соединить все это вместе"?

  2. каково "правильное" расположение обратных вызовов и как указать обратный вызов "успех/ошибка"? Я имею в виду синтаксически?Я не совсем понимаю синтаксис регистрации обратных вызовов в магистрали...


если это действительно сложная работа, то мы можем вызвать jQuery.ajax в представлении и передать this.successMethod или this.errorMethod как успех/ошибка обратного вызова?? Будет ли она работать?



мне нужно синхронизировать с образом мышления позвоночника - я знаю, что я определенно чего-то не хватает w.r.t., синхронизация целых коллекций.

567   11  

11 ответов:

моя непосредственная мысль заключается не в том, чтобы переопределить метод при сохранении метода на позвоночнике.Коллекция, но оберните коллекцию в другой костяк.Модель и переопределить метод toJSON на этом. Потом Позвоночник.js будет рассматривать модель как единый ресурс, и вам не нужно взломать путь назад, который слишком много думает.

обратите внимание, что костяк.Коллекция имеет метод toJSON, поэтому большая часть вашей работы выполняется за вас. Вам просто нужно прокси-метод toJSON вашей оболочки позвоночника.Модель Позвоночник.коллекция.

var MyCollectionWrapper = Backbone.Model.extend({
url: "/bulkupload",

//something to save?
toJSON: function() {
    return this.model.toJSON(); // where model is the collection class YOU defined above
 }

});

очень простой...

Backbone.Collection.prototype.save = function (options) {
    Backbone.sync("create", this, options);
};

...даст вашим коллекциям метод сохранения. Имейте в виду, что это всегда будет размещать все модели коллекции на сервере независимо от того, что изменилось. параметры - это просто обычные параметры jQuery ajax.

Я закончил тем, что просто "сохранить" как метод и вызвал $.Аякс внутри него. Это дало мне больше контроля над ним без необходимости добавлять класс обертки, как предложил @brandgonesurfing (хотя мне очень нравится идея:), как уже упоминалось, поскольку у меня уже была коллекция.метод toJSON () переопределил все, что я приземлился, используя его в вызове ajax...

надеюсь, что это поможет кому-то, кто натыкается на него...

это действительно зависит от того, что контракт между клиентом и сервером. Вот упрощенный пример CoffeeScript, где PUT to /parent/:parent_id/children С {"children":[{child1},{child2}]} заменит детей родителя на то, что находится в PUT и return {"children":[{child1},{child2}]}:

class ChildElementCollection extends Backbone.Collection
  model: Backbone.Model
  initialize: ->
    @bind 'add', (model) -> model.set('parent_id', @parent.id)

  url: -> "#{@parent.url()}/children" # let's say that @parent.url() == '/parent/1'
  save: ->
    response = Backbone.sync('update', @, url: @url(), contentType: 'application/json', data: JSON.stringify(children: @toJSON()))
    response.done (models) => @reset models.children
    return response

это довольно простой пример, вы можете сделать гораздо больше... это действительно зависит от того, в каком состоянии находятся ваши данные при выполнении save (), в каком состоянии они должны быть отправлены на сервер и что дает сервер спина.

если ваш сервер в порядке с PUT of [{child1},{child2], тогда ваш позвоночник.линия синхронизации может измениться на response = Backbone.sync('update', @toJSON(), url: @url(), contentType: 'application/json').

ответ зависит от того, что вы хотите сделать с коллекцией на стороне сервера.

Если вам нужно отправить дополнительные данные С сообщением вам может понадобиться модель оболочки или реляционная модель.

С модель фантик вы всегда должны написать свой собственный парсить способ:

var Occupants = Backbone.Collection.extend({
    model: Person
});

var House = Backbone.Model.extend({
    url: function (){
        return "/house/"+this.id;
    },
    parse: function(response){
        response.occupants = new Occupants(response.occupants)
        return response;
    }
});

реляционной модели лучше, я думаю, потому что вы можете настроить их проще и вы можете регулировать с includeInJSON опция, атрибуты которой нужно поместить в json, который вы отправляете в свою службу rest.

var House = Backbone.RelationalModel.extend({
    url: function (){
        return "/house/"+this.id;
    },
    relations: [
        {
            type: Backbone.HasMany,
            key: 'occupants',
            relatedModel: Person,
            includeInJSON: ["id"],
            reverseRelation: {
                key: 'livesIn'
            }
        }
    ]
});

если вы не отправляете дополнительные данные вы можете синхронизировать саму коллекцию. Вы должны добавить сохранить метод для вашей коллекции (или прототипа коллекции) в этом случае:

var Occupants = Backbone.Collection.extend({
    url: "/concrete-house/occupants",
    model: Person,
    save: function (options) {
        this.sync("update", this, options);
    }
});

Я также был удивлен, что базовые коллекции не имеют встроенного сохранения. Вот что я положил на мою коллекцию позвоночника, чтобы сделать это. Я определенно не хочу повторять каждую модель в коллекции и сохранять независимо. Кроме того, я использую магистраль на бэкэнде, используя узел, поэтому я переопределяю родной Backbone.sync чтобы сохранить в плоский файл на моем маленьком проекте-но код должен быть почти таким же:

    save: function(){                                                                                                                                                                                                                                                                                                                                                     
      Backbone.sync('save', this, {                                                                                                                                                                                                                                                                                                                                     
        success: function(){                                                                                                                                                                                                                                                                                                                                          
          console.log('users saved!');                                                                                                                                                                                                                                                                                                                              
        }                                                                                                                                                                                                                                                                                                                                                             
      });                                                                                                                                                                                                                                                                                                                                                               
    }

старый поток я знаю, что я в конечном итоге сделал следующее:

Backbone.Collection.prototype.save = function (options) {
            // create a tmp collection, with the changed models, and the url
            var tmpCollection = new Backbone.Collection( this.changed() );
            tmpCollection.url = this.url;
            // sync
            Backbone.sync("create", tmpCollection, options);
        };
        Backbone.Collection.prototype.changed = function (options) {
            // return only the changed models.
            return this.models.filter( function(m){
                return m.hasChanged()
            });
        };
// and sync the diffs.
self.userCollection.save();

довольно напрягаться вперед :)

вот простой пример:

var Books = Backbone.Collection.extend({
model: Book,
url: function() {
  return '/books/';
},
save: function(){
  Backbone.sync('create', this, {
    success: function() {
      console.log('Saved!');
    }
  });
 }
});

при вызове метода save () в вашей коллекции он отправит запрос метода PUT на определенный URL-адрес.

Я бы попробовал что-то вроде:

var CollectionSync = function(method, model, [options]) {
    // do similar things to Backbone.sync
}

var MyCollection = Backbone.Collection.extend({
    sync: CollectionSync,
    model: MyModel,
    getChanged: function() {
        // return a list of models that have changed by checking hasChanged()
    },
    save: function(attributes, options) {
        // do similar things as Model.save
    }
});

( https://stackoverflow.com/a/11085198/137067 )

принятый ответ довольно хорош, но я могу пойти еще на один шаг и дать вам код, который обеспечит запуск правильных событий для ваших слушателей, а также позволит вам передавать обратные вызовы событий ajax:

save: function( options ) {
  var self = this;

  var success = options.success;
  var error = options.error;
  var complete = options.complete;

  options.success = function( response, status, xhr ) {
    self.trigger('sync', self, response, options);
    if (success) return success.apply(this, arguments);
  };

  options.error = function( response, status, xhr ) {
    self.trigger('error', self, response, options);
    if (error) return error.apply(this, arguments);
  };

  options.complete = function( response, status, xhr ) {
    if (complete) return complete.apply(this, arguments);
  }

  Backbone.sync('create', this, options);
}

для тех, кто все еще использует позвоночник.js в 2017 году принятый ответ не работает.

Попробуйте удалить переопределение toJSON () в модели оболочки и вызвать toJSON в коллекции при создании экземпляра оболочки модели.

new ModelWrapper(Collection.toJSON());

Comments

    Ничего не найдено.