2

親コレクションのメニュー属性を持つすべての新しいMenuItemモデルが必要です。これは機能しない基本的な例です(this.collectionはMenuItemのデフォルト関数で定義されていないため)

var MenuItem, Menu, menu;

MenuItem = Backbone.Model.extend({
  defaults: function() {
    return {
      menu: this.collection.name
    }
  },

  // Fake Backbone sync
  sync: function(method, model, options) {
    if(typeof model.cid != 'undefined') {
      var cid = model.cid;
      model.unset('cid').set({id:cid}, {silent:true});
    }
    options.success(model);
  }

});

Menu = Backbone.Collection.extend({
  model: MenuItem,
  initialize: function(options) {
    this.name = options.name;
  }
});

menu = new Menu({name: "footer"});

menu.create({title: "Page", url: "/page"}, {
  success: function(model){
    console.log(model.get("menu")) // expect to be "footer"
  }
})
4

2 に答える 2

1

コレクションのcreateメソッドをオーバーライドすることで修正できましたが、これが正しい方法かどうかはまだわかりません。

create: function(attributes, options) {
  return Backbone.Collection.prototype.create.call(
    this,
    _.extend({menu: this.name}, attributes),
    options
  );
}
于 2012-11-05T13:26:56.070 に答える
1

新しいモデルが存在するすべての可能性について:

文書化されていないコレクション関数へのフックがうまく機能する_prepareModel ことがわかりました。

ジェネリックコレクション

このコレクションをそのまま使用して、デフォルトのバックボーンコレクションを置き換えることができます。追加します

  • 新しいモデルインスタンスとオプションonNewModelを受け取る、オーバーライドする新しい関数
  • new-model同じデータを送信するカスタムイベント。
var Collection = Backbone.Collection.extend({
    /**
     * Hook into the native _prepareModel to offer a standard hook
     * when new models are added to the collection.
     */
    _prepareModel: function(model, options) {
        model = Collection.__super__._prepareModel.apply(this, arguments);
        if (model) {
            // call our new custom callback
            this.onNewModel(model, options);
            // trigger a new custom event
            this.trigger('new-model', model, options);
        }
        return model;
    },

    // Called when adding a new model to the collection.
    onNewModel: _.noop,
});

そして、あなた自身のコレクションは次のようになります。

var Menu = Collection.extend({
    model: MenuItem,
    initialize: function(models, options) {
        this.name = options.name;
    }
    onNewModel: function(model, options) {
        model.set({ menu: model.get('menu') || this.name });
    },
});

model内のバックボーンModelインスタンスであることが保証されますonNewModel

コンセプトの証明

// The generic collection, put that in a file and include it once in your project.
var Collection = Backbone.Collection.extend({
  /**
   * Hook into the native _prepareModel to offer a standard hook
   * when new models are added to the collection.
   */
  _prepareModel: function(model, options) {
    model = Collection.__super__._prepareModel.apply(this, arguments);
    if (model) {
      this.onNewModel(model, options);
      this.trigger('new-model', model, options);
    }
    return model;
  },

  // Called when adding a new model to the collection.
  onNewModel: _.noop,
});

// Extend from the generic collection to make your own.
var Menu = Collection.extend({
  initialize: function(models, options) {
    this.name = options.name;
  },
  onNewModel: function(model, options) {
    model.set({
      menu: model.get('menu') || this.name
    });
    
    console.log("onNewModel menu:", model.get('menu'));
  },
});

// then use it
var menu = new Menu([
  // works with bare objects
  {
    title: "Page",
    url: "/page"
  },
  // or Model instances
  new Backbone.Model({
    title: "Other Page"
  })
], {
  name: "footer" // the collection option
});

// Listen to the custom event if you want
Backbone.listenTo(menu, 'new-model', function(model, options) {
    console.log("'new-model' triggered with", model.get('title'));
});

// or other collection methods
menu.add({
  title: "Page",
  menu: "won't be overriden"
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>

于 2016-11-07T22:47:47.930 に答える