web-dev-qa-db-ja.com

同期時にモデルプロパティを除外する(Backbone.js)

同期するときにモデルから特定のプロパティを除外する方法はありますか?

たとえば、ビューステートに関するモデル情報を保持しています。ピッカーモジュールがあり、このモジュールがモデルのselected属性を切り替えるだけだとします。後で、コレクションで.save()を呼び出すとき、selectedの値を無視して、サーバーへの同期から除外したいと思います。

そうするきれいな方法はありますか?

詳細が必要な場合はお知らせください

43
Simon Boudrias

これは最良の解決策のようです(@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);
    }
});

そのため、モデルインスタンスの保存関数を上書きしますが、不要なデータをフィルターで除外し、それを親プロトタイプ関数にプロキシします。

47
Simon Boudrias

Underscore 1.3.3では pick が追加され、1.4.0では omit が追加されました。これは、モデルのtoJSON関数をホワイトリスト属性にオーバーライドするために非常に簡単に使用できます_.pickを使用するか、_.omitを使用するブラックリスト属性を使用します。

また、toJSONはデータをサーバーに渡すためにsyncコマンドで使用されるため、toJSONを使用する他の場所でこれらのフィールドが必要ない限り、これは良いソリューションだと思います。

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

私のソリューションは上記のすべてを組み合わせています。ブラックリストの代わりにホワイトリストを使用してください..これは一般的に良いルールです

定義する

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

実際、この動作が永続的であるとは思わないため、バックボーンの保存または同期機能を台無しにせずにこれを達成するはるかに簡単な方法があります

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を備えたバックボーンで使用できます...

6
Pascal

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

いくつかの答えに基づいて、これは、contentType if 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);
},
3
Ross Allen

Set options.attrsを使用すると、APIパラメーターをカスタマイズできます。

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

savetoJSONを使用するため、オーバーライドします。

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

ただし、toJSONを使用しており、たとえばビューでselectedが必要な場合は機能しない場合があります。それ以外の場合は、おそらくsaveメソッドをオーバーライドする必要があります。

2
rinat.io

必要な値のみを設定するには、HTTP POSTの代わりにHTTP PATCHを使用します。バックボーン側で、saveメソッドにパッチ属性を追加するだけです:

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

この属性でsaveを使用すると、dataとして渡されたフィールドのみがサーバーに送信されます。

0
Pavel Sedek

1回限りの場合は、mode.unset('selected', { silent:true })(変更イベントの発生を避けるためだけにサイレントが設定されます)を使用して、属性を削除できます。ただし、保存後に再設定します。

これは、上記の解決策の1つを完全に推奨することです。さらに、これがより定期的に必要なものである場合。

0
Tallmaris

この同じ問題を抱えて、私は助けることができる小さなモジュールを作成することにしました: https://github.com/lupugabriel1/backbone-model-save

これはあなたのモデルでそれを使用する方法です:

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