Я хорошо знаю, что это можно сделать, и я просмотрел довольно много мест (в том числе: Лучшая практика для сохранения всей коллекции? ). Но мне все еще не ясно, «как именно» это написано в коде? (сообщение объясняет это на английском языке. Было бы здорово получить конкретное объяснение 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?
*/
}
После того, как «представление» завершено с обработкой, оно отвечает за указание коллекции «сохранить» себя на сервере (способном обрабатывать массовый запрос на обновление / создание).
Возникающие вопросы:
- Как / что написать в коде, чтобы «связать все вместе»?
- Какое «правильное» расположение обратных вызовов и как указать обратный вызов «успех / ошибка»? Я имею в виду синтаксически? Мне непонятен синтаксис регистрации обратных вызовов в магистрали ...
Если это действительно сложная задача, можем ли мы вызвать jQuery.ajax в представлении и передать this.successMethod
или this.errorMethod
как обратные вызовы успеха / ошибки ?? Это будет работать?
Мне нужно синхронизироваться с мышлением магистрали - я знаю, что определенно что-то упустил, синхронизируя целые коллекции.
источник
Ответы:
Моя немедленная мысль - не переопределять метод метода сохранения в Backbone.Collection, а обернуть коллекцию в другой Backbone.Model и переопределить метод toJSON для этого. Тогда Backbone.js будет рассматривать модель как единый ресурс, и вам не придется слишком много ломать голову, как backone думает.
Обратите внимание, что 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 } });
источник
getURL(model)
аргумент модели и не выполняет никаких сравнений ... кажется, намеренно намеренноОчень простой ...
Backbone.Collection.prototype.save = function (options) { Backbone.sync("create", this, options); };
... предоставит вашим коллекциям метод сохранения. Имейте в виду, что это всегда будет отправлять все модели коллекции на сервер независимо от того, что изменилось. Параметры - это обычные параметры jQuery ajax.
источник
return Backbone.sync..
еще больше Backbonish.В итоге у меня просто был метод, похожий на «save», и я вызвал в нем $ .ajax. Это дало мне больше контроля над ним без необходимости добавлять класс-оболочку, как предлагал @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')
.источник
Ответ зависит от того, что вы хотите делать с коллекцией на стороне сервера.
Если вам нужно отправить дополнительные данные с сообщением, вам может потребоваться модель оболочки или реляционная модель. .
С моделью оболочки вам всегда нужно писать свой собственный метод синтаксического анализа :
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, который вы отправляете в службу отдыха.
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!'); } }); }
источник
save: function (options) { Backbone.sync('save', this, options); }
Старый поток, который я знаю, в итоге я сделал следующее:
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); }
источник
Для тех, кто все еще использует backbone.js в 2017 году, принятый ответ не работает.
Попробуйте удалить переопределение toJSON () в модели оболочки и вызвать toJSON в коллекции при создании экземпляра оболочки модели.
new ModelWrapper(Collection.toJSON());
источник