«Как» сохранить всю коллекцию в Backbone.js – Backbone.sync или jQuery.ajax?

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

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

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 как обратные вызовы успеха / ошибки ?? Это будет работать?

Мне нужно синхронизировать с мышлением позвоночника – я знаю, что я определенно пропустил что-то, синхронизируя целые коллекции.

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

Обратите внимание, что Backbone.Collection имеет метод toJSON, поэтому большая часть вашей работы выполняется для вас. Вам просто нужно проксировать метод toJSON вашей оболочки Backbone.Model на Backbone.collection.

 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.

Я закончил тем, что просто использовал метод «save» и назвал $ .ajax внутри него. Это дало мне больше контроля над этим без необходимости добавлять class-оболочку, как предлагал @brandgonesurfing (хотя мне очень нравится идея 🙂 Как уже упоминалось, поскольку у меня уже был метод collection.toJSON (), который был переопределен, все, что я приземлился, использовал его в вызове ajax …

Надеюсь, это поможет кому-то, кто наткнулся на него …

Это действительно зависит от контракта между клиентом и сервером. Вот упрощенный пример CoffeeScript, в котором PUT to /parent/:parent_id/children с {"children":[{child1},{child2}]} заменит детей родителя на то, что находится в PUT, и возвращает {"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 [{child1},{child2] , то строка Backbone.sync может измениться на response = Backbone.sync('update', @toJSON(), url: @url(), contentType: 'application/json') .

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

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

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

 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 не имеют встроенной памяти. Вот что я надел на свою основную коллекцию, чтобы сделать это. Я определенно не хочу перебирать каждую модель в коллекции и сохранять самостоятельно. Кроме того, я использую Backbone на бэкэнд с помощью Node, поэтому я переопределяю родной 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 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 )

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

 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.

Принятый ответ довольно хорош, но я могу сделать еще один шаг и дать вам код, который обеспечит, чтобы надлежащие события были уволены для ваших слушателей, а также позволяли вам переходить в ответные обратные вызовы 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); } 

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

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

 new ModelWrapper(Collection.toJSON()); 
  • Пропустите Blob через ajax, чтобы сгенерировать файл
  • Как отправить массив параметров запроса на сервлет с помощью jQuery $ .ajax?
  • Динамически добавлять элемент в элемент управления jQuery Select2, который использует AJAX
  • Как определить направление прокрутки
  • Использование .text () для извлечения только текста, не вложенного в дочерние tags
  • Вызов «WebMethod» с jQuery в ASP.NET WebForms
  • Как заставить $ .serialize () учитывать отключенных: элементы ввода?
  • Ajax / jQuery - загрузить содержимое веб-страницы в div на загрузку страницы?
  • Холст HTML5 100% Ширина Высота видового экрана?
  • Как изменить цвет текста с помощью jQuery?
  • как сохранить массив в jQuery cookie?
  • Interesting Posts

    Emacs открывает файлы в новом фрейме при открытии с помощью «open -a»

    Программа захвата экрана с возможностью загрузки на сайты обмена изображениями

    Почему диалоговое окно брандмауэра Mac OS X периодически появляется и исчезает само по себе (без ответа) под Snow Leopard?

    Тип java.lang.CharSequence не может быть разрешен в объявлении пакета

    Ошибка запуска Tomcat из NetBeans – «127.0.0.1 *» не распознается как внутренняя или внешняя команда

    Почему мой компьютер не будет спать автоматически?

    Насколько полно заполнено для механических жестких дисков?

    Выбор канала WiFi 2,4 ГГц, когда все неперекрывающиеся каналы переполнены

    Загрузка ресурса из любого места в пути classpath

    Как я могу разблокировать документ Microsoft .docx?

    Как получить std :: векторный указатель на необработанные данные?

    Могут ли новые версии JRE запускать Java-программы, скомпилированные со старыми версиями JDK?

    RAID 1 без защиты кеша – ZMCP / резервная батарея

    HttpEntity устарела на Android сейчас, какова альтернатива?

    Значимые миниатюры для видео с использованием FFmpeg

    Давайте будем гением компьютера.