web-dev-qa-db-fra.com

Comment accéder à une vue composite à partir d'une instance de vue d'élément dans Backbone Marionette

La situation de base est la suivante:

J'ai une vue composite et une vue d'article. Je construis la vue Composite en lui passant un modèle et une collection. Les données du modèle sont utilisées pour remplir le modèle pour la vue composite. Les données de collecte sont utilisées pour remplir la vue d'élément pour la vue composite.

Ce que je veux faire est le suivant: dans un assistant de modèle pour la vue Article, je veux accéder aux données du modèle pour la vue composite. J'ai jusqu'à accéder à l'instance de vue de la vue d'élément. J'ai pensé que cela pourrait me donner une idée de la vue composite, d'où je pourrais accéder à son modèle, mais ce n'est pas le cas.

Existe-t-il un moyen de le faire - accéder à l'instance de vue composite à partir d'une de ses instances de vue d'élément?

Merci

--Justin Wyllie

29
user911625

Si vous souhaitez accéder aux données du parent CompositeView, vous pouvez effectuer différentes opérations.

  1. Soit passez ces données directement à ItemView via la fonction d'assistance itemViewOptions sur CompositeView. Remarque: cette option est devenue childViewOptions dans Marionette 2.

  2. Appelez une méthode directement sur toutes les vues enfants à partir de CompositeView et passez ce que vous voulez dans cette méthode.

  3. Déclenchez un événement sur ou écouté par ItemView.

Aucune de ces options n'accède directement à la vue parent depuis l'enfant mais doit faire ce que vous voulez. Ci-dessous se trouve le code pour savoir comment utiliser chacune de ces approches pour passer le modèle de CompositeView à la vue des enfants.

// Pass model into ItemView on init
var MyItemView = Backbone.Marionette.ItemView.extend({
  initialize : function (options) {
    this.parentsModel = options.parentsModel;
  }
});
var MyCompView = Backbone.Marionette.CompositeView.extend({
  itemViewOptions : function () { return { parentsModel: this.model }; }
  itemView : MyItemView
});


// Invoke function on ItemView, passing data in
var MyItemView = Backbone.Marionette.ItemView.extend({
  doSomethingWithParent : function (parentModel) {
    // do cool thing with parentModel
  }
});
var MyCompView = Backbone.Marionette.CompositeView.extend({
  itemView : MyItemView,
  onRender : function () {
    this.children.call("doSomethingWithParent", this.model);
  }
});


// Trigger event that ItemView knows about
var MyItemView = Backbone.Marionette.ItemView.extend({
  initialize : function () {
    this.listenTo(this, "special:event", function (parentModel) {
      // Do cool things
    });
  }
});
var MyCompView = Backbone.Marionette.CompositeView.extend({
  itemView : MyItemView,
  onRender : function () {
    this.children.each(_.bind(function (childView) {
      childView.trigger("special:event", this.model);
     }, this));
  }
});
33
Andrew Hubbs

Je n'ai pas répondu à la question. Mais changer l'approche fonctionne. Au lieu d'essayer d'accéder à la vue composite "parent" à partir de la vue article, j'accède à la vue article à partir de la vue composite:

https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.collectionview.md#onbeforeitemadded-callback

Je peux modifier le modèle de la vue de l'élément en cours (basé sur une valeur dans le modèle de la vue composite).

1
user911625

J'ai pensé partager comment la suggestion d'Andrew Hubbs m'a aidé. J'essayais d'afficher une propriété de modèle parent en ligne avec mon modèle d'élément. J'ai utilisé la propriété templateHelpers de Marionette pour ce faire en combinaison avec l'une des suggestions d'Andrew.

J'ai essayé de garder l'exemple bref:

Exemple de modèle composite - modèle myView:

<h1>Page {{name}}</h1>
<h6>Children</h6>
<ul></ul>

Exemple de modèle d'élément - myItemTemplate:

{{name}} is child of: {{getParentName}}

Vues:

App.module( 'App.View', function( View ){

    View.MyItemView = Marionette.ItemView.extend({

        initialize: function( options ) {
            this.parentModel = options.parentModel;
        },

        template: myItemTemplate,

        tagName: 'li',

        templateHelpers: function() {

            var view = this;

            return {
                // Called by item template, returns parent model 'name' property.
                getParentName: function() {
                    return view.parentModel.get('name');
                }

            };
        }

    });

    View.MyView = Marionette.CompositeView.extend({

        template: myViewTemplate,

        itemView: View.MyItemView,

        itemViewContainer: 'ul',

        itemViewOptions: function() {

            return { parentModel: this.model };

        }

    });

});

Un exemple de la façon dont cela serait mis en œuvre:

// example of how implementation
// parent model has an attribute called 'children', which is a collection of models
var children = parent.get('children');

var view = new App.View.MyView( { model: parent, collection: children } );

App.mainRegion.show( view );
1
alettieri