Подтвердить что ты не робот

Исключить свойства модели при синхронизации (Backbone.js)

Есть ли способ исключить определенное свойство из моей модели при синхронизации?

Например, я сохраняю в своей модели информацию о каком-либо состоянии представления. Скажем, у меня есть сборщик, и этот модуль просто переключает атрибуты selected на мою модель. Позже, когда я вызываю .save() в моей коллекции, я хочу проигнорировать значение selected и исключить его из синхронизации на сервер.

Есть ли чистый способ сделать это?

(дайте мне знать, если вы хотите получить более подробную информацию)

4b9b3361

Ответ 1

Это похоже на лучшее решение (на основе заданного вопроса @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);
    }
});

Таким образом, мы перезаписываем функцию сохранения в экземпляре модели, но мы просто отфильтровываем данные, которые нам не нужны, а затем мы прокси-сервер к исходной функции прототипа.

Ответ 2

В Underscore 1.3.3 они добавили pick, а в 1.4.0 они добавили omit, который можно использовать очень просто, чтобы переопределить вашу модель toJSON для атрибутов whitelist с атрибутами _.pick или черного списка с помощью _.omit.

А поскольку toJSON используется командой sync для передачи данных на сервер, я думаю, что это хорошее решение, если вы не хотите использовать эти поля везде, где вы используете toJSON.

Backbone.Model.extend({
    blacklist: ['selected',],
    toJSON: function(options) {
        return _.omit(this.attributes, this.blacklist);
    },
});

Ответ 3

мое решение объединяет все вышеперечисленное. просто используйте белый список вместо черного. Это хорошее правило вообще

define

          attrWhiteList:['id','biography','status'],

а затем перезапишите сохранение

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

Ответ 4

На самом деле существует гораздо более простой способ достичь этого, не вступая в функции сохранения или синхронизации с базой, поскольку вы не ожидали бы, что это поведение будет постоянным.

если вы посмотрите на строку backbone.js 1145, вы увидите, что

// 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));
    }

Это означает, что вы можете переопределить часть данных xhr, поместив данные в свои параметры

Так как для сохранения базы требуется model.save([attributes], [options])

Но помните, что атрибуты, такие как id, могут быть необходимы для правильного сохранения

Пример

model.save( {}, { data: JSON.stringify(data) } ) ; 

Итак, вы должны делать что-то вроде этого

var data = { id : model.id , otherAttributes : 'value' }  ;  
model.save( {}, { data : JSON.stringify(data) } );

Это хорошо подходит для меня и может использоваться с любой основой с xhr, например, с помощью fetch, save, delete,...

Ответ 5

Основываясь на нескольких ответах, это учитывает случаи нулевых объектов и условные условия в Backbone, которые не отправили contentType, если options.data уже установлен:

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

Ответ 6

Так как save использует toJSON, мы переопределяем его:

    toJSON: function(options) {
        var attr = _.clone(this.attributes);
        delete attr.selected;
        return attr;
    },

Но это может не сработать, если вы используете toJSON и, например, нуждаетесь в selected в представлениях. В противном случае вам, вероятно, придется переопределить метод save.

Ответ 7

Set options.attrs позволит вам настроить api param:

var model = new Backbone.Model();
model.save(null, {
  wait: true,
  success: function() {
  },
  attrs: _.omit(model.attributes, 'selected')
});

Ответ 8

Я обнаружил некоторые проблемы с принятым решением, так как options.data изменяет способ вызова Backbone. Лучше использовать options.attrs следующим образом:

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

Ответ 9

Если это одноразовый случай, вы можете использовать mode.unset('selected', { silent:true }) (тихий установлен только для того, чтобы избежать срабатывания события изменения), чтобы удалить атрибут... Это имеет не очень хороший контр-эффект от необходимости переустановите его после сохранения.

Это говорит о том, что я полностью поддерживаю одно из решений выше. Более того, если это то, что вам нужно на регулярной основе.

Ответ 10

Чтобы установить только нужные значения, используйте HTTP PATCH insead HTTP POST. На стороне основы просто добавьте атрибут патча к методу сохранения:

entity.save(data,{patch:true})

Используя сохранение с этим атрибутом, на сервер отправляются только те поля, которые передаются как data.

Ответ 11

Имея эту же проблему, я решил создать небольшой модуль, который может помочь: https://github.com/lupugabriel1/backbone-model-save

Вот как вы можете использовать его в своих моделях:

var myModel = new Backbone.ModelSave.extend({
    notSync: ['name', 'age']
});