2012-11-07 6 views
0

Je rencontre des problèmes de compréhension de la liaison d'événements dans une sous-vue Backbone. Mon point de vue est défini comme suit:Comment lier un événement click dans une sous-vue Backbone

TenantView = Backbone.View.extend({ 
    events: { 
    "click": "setActive" 
    }, 
    initialize: function() { 
    this.parentEl = this.options.parentEl; 
    return this.render(); 
    }, 
    template: new EJS({ 
    url: '/scripts/templates/tenant.ejs' 
    }), 
    render: function() { 
    $(this.parentEl).children('ul').append(this.template.render(this.model)); 
    return this; 
    }, 
    setActive: function(event) { 
    return this.model.set('active', true); 
    } 
}); 

Le modèle consiste simplement d'un li containg un a. Fait de cette façon, les clics sur les événements de ma vue ne sont pas interceptés, ma méthode setActive n'est jamais déclenchée.

Lorsque j'étend ma vue par une propriété el comme el: 'li' l'une de mes (2) vues agit correctement et déclenche la fonction setActive. La deuxième vue ne réagit pas du tout. Si j'inspecte la propriété el lors de l'initialisation des vues, la propriété el de la vue de travail pointe vers la droite li, les vues défaillantes el pointent vers la première li qui se trouve dans la page.

Comme on peut le voir, je suis totalement perdu quand il s'agit de la signification de la propriété el.

La question est, comment puis-je lier un clic sur la vue à cette fonction très vues setActive?

Quelqu'un peut-il m'éclairer s'il vous plaît?

Cordialement Felix

Répondre

2

La première chose, vous pouvez lire documentation et this. Une explication sur el est donnée ici.

Comme TenantView a parentEl propriété, je suppose qu'il est rendu à partir de certains parent_view. Je suggérerais une approche comme ci-dessous et essayer.

var ChildView = Backbone.View.extend({ 
    tagName : "li", // change it according to your needs 

    events : { 
    "click": "setActive" 
    }, 

    initialize : function() { 
    _.bindAll(this, "setActive"); 
    // code to initialize child_view 
    }, 

    render : function() { 
    // as I'm not familiar with the way you are using template, 
    // I've put simple call to render template, but it should render the 
    // content to be kept inside "li" tag 
    this.$el.html(this.template()); 

    return this; 
    }, 

    setActive : function(event) { 
    // code to be executed in event callback 
    } 
}); 


var ParentView = Backbone.View.extend({ 
    el : "#parent_view_el", 

    initialize : function() { 
    // parent view initialization code 
    }, 

    render : function() { 
    // a place from where ChildView is initialized 
    // might be a loop through collection to initialize more than one child views 
    // passing individual model to the view 

    var child_view = new ChildView(); 

    this.$("ul").append(child_view.render().$el); // equivalent to this.$el.find("ul") 

    return this; 
    } 
}); 

Espérons que ça aide !!

+0

Cyclone, merci pour votre réponse. En fait, c'est presque ce que je fais. La propriété parentEl pointe vers la propriété el de CollectionViews (qui est un ul), afin que je puisse rendre mes ChildViews dans le ul. Dans mon parent, CollectionView, je parcours les modèles de collections et crée une instance ChildView pour chacun. J'ai le sentiment que cette approche est totalement fausse. – GeorgieF

+0

Hmmm, c'est ce que j'ai suivi, fonctionne plutôt bien pour moi :) – Cyclone

+0

Lecture [this] (http://stackoverflow.com/questions/5624929/backbone-view-el-confusion) effectivement résolu mon problème. Voir mon commentaire ci-dessous. Merci encore pour la contribution. – GeorgieF

0

Vous avez genre de backbones handicapées de comportement naturel en introduisant votre parentEl propriété et contournent la création d'un élément de vue. En principe, vous ne câlinez jamais la propriété `elz 'à n'importe quoi.

Si je reçois votre code correctement, le TenantView est un élément de liste unique dans une liste de locataires.

Dans votre TenantView vous pouvez le faire pour tirer parti de backbones construit dans les événements:

render: function() { 
    this.setElement(this.template.render(this.model)); 
    $(this.parentEl).children('ul').append(this.$el); 
    return this; 
} 

La fonction setElement utilisera la valeur de retour de vous template fonction de câbler l'élément de vues et également configurer les événements pour vous . Dans la documentation, il est suggéré d'utiliser setElement pour simplement attribuer quelque chose à la propriété el. Il y a aussi la bonne propriété $el qui contiendra un objet jQuery (ou Zepto) en cache de l'élément de votre vue.

Pour aller plus dans la voie de colonne vertébrale personnellement, je considérerais quelque chose comme ceci:

var TenantView = Backbone.View.extend({ 
    // ========= 
    // = Setup = 
    // ========= 

    events: { 
     "click": "setActive" 
    }, 

    template: new EJS({ 
     url: '/scripts/templates/tenant.ejs' 
    }), 

    // ============= 
    // = Lifecycle = 
    // ============= 

    initialize: function(model, options) { 
     this.render(); 
    }, 

    render: function() { 
     var content = this.template.render(this.model); 
     this.$el.html(content); 
     return this; 
    }, 

    // ========== 
    // = Events = 
    // ========== 

    setActive: function(event) { 
     return this.model.set('active', true); 
    } 

}); 


var TenantList = Backbone.View.extend({ 

    // ========= 
    // = Setup = 
    // ========= 

    id: "tenantList", 
    tagName: "ul", 

    // ============= 
    // = Lifecycle = 
    // ============= 

    initialize: function() { 
     this.render(); 
    }, 

    render: function() { 
     if (this.collection.length > 0) { 
      this.renderChildren(); 
     } 
    }, 

    renderChildren: function() { 
     var that = this; 

     this.collection.each(function(tenant) { 
      that.$el.append(new TenantView(tenant).$el); 
     }); 
    } 
}); 
+0

Torsten, merci pour votre réponse. setElement semble correctement définir la propriété el de mes vues pendant le rendu maintenant.Malheureusement, les événements de clic ne sont pas capturés dans les deux cas. Je pense que toute mon approche de rendre ChildViews dans un CollectionView est totalement fausse. – GeorgieF

+0

Eh bien dans une sorte de manière ... Backbone sorte de vous attend d'avoir un élément après l'initialisation et seulement remplir cela avec la fonction de rendu. En théorie, la fonction 'setElement' devrait prendre en charge les événements. Quelle version de backbone utilisez-vous? –

+0

J'utilise 0.9.2. Ce qui a résolu le problème jusqu'ici était de mettre 'tagname' à 'li' pour le ChildView. Ensuite, retirez le li du modèle. J'ai changé la méthode de rendu de mon ChildView à: this.el.innerHTML = this.template.render (this.model) et ai changé la méthode de rendu de mon CollectionView à: $ (this.el) .children ('ul'). append (viewInstance.render(). el) où viewInstance est parcouru. Je ne suis toujours pas sûr que cette approche soit la bonne. – GeorgieF

Questions connexes