2011-09-21 20 views
9

CellModels'in bir CellCollection öğesini içeren bir BoardView var. Koleksiyonu db'den aldım ve sonra CellViews'ı yaratıyorum.backbone.js - click olayından bir modele erişme

Bu, tüm BoardView üzerinde bir tıklama olayı aracılığıyla bir CellModel erişmeye çalışana kadar yüzme çalışır. Temel modellere hiç ulaşamam ... sadece görüşler. Bunu yapmanın bir yolu var mı?

Ben aşağıdaki ilgili kod eklemek için teşebbüs ettik: o tahta özgü mantığı içerir çünkü

CellModel = Backbone.Model.extend({}); 

CellCollection = Backbone.Collection.extend({ 
    model : CellModel 
}); 

CellView = Backbone.View.extend({ 
    className : 'cell', 
}); 

BoardView = Backbone.View.extend({ 
    this.model.cells = new CellCollection(); 

    render : function() { 
     this.cellList = this.$('.cells'); 
     return this; 
    }, 

    allCells : function(cells) { 
     this.cellList.html(''); 
     this.model.cells.each(this.addCell); 
     return this; 
    }, 

    addCell : function(cell) { 
     var view = new Views.CellView({ 
      model : cell 
     }).render(); 

     this.cellList.append(view.el); 
    }, 

    events : { 
     'click .cell' : 'analyzeCellClick', 
    }, 

    analyzeCellClick : function(e) { 
     // ????????? 
    } 
}); 

Ben BoardView değil CellView üzerinde "olur" için tık yeterlidir.

cevap

11
Burada kullanabilir, en az iki yaklaşımın düşünebiliriz

:

  1. başlatma sırasında CellView için BoardView geçirin ve sonra CellView olayı işlemek:

    var CellView = Backbone.View.extend({ 
        className : 'cell', 
    
        initialize: function(opts) { 
         this.parent = opts.parent 
        }, 
    
        events : { 
         'click' : 'analyzeCellClick', 
        }, 
    
        analyzeCellClick : function() { 
         // pass the relevant CellModel to the BoardView 
         this.parent.analyzeCellClick(this.model); 
        } 
    }); 
    
    var BoardView = Backbone.View.extend({ 
        // ... 
    
        addCell : function(cell) { 
         var view = new Views.CellView({ 
          model : cell, 
          parent : this 
         }).render(); 
    
         this.cellList.append(view.el); 
        }, 
    
        analyzeCellClick : function(cell) { 
         // do something with cell 
        } 
    }); 
    

    Bu çalışır, ama görüşlerin birbirlerinin yöntemlerini çağırmamasını tercih ederim, çünkü onları daha sıkı bir şekilde birleştirir. Bunu işlemek zaman

  2. DOM CellModel id takın: Yukarıdaki sıkı bağlantı önler ki

    var CellView = Backbone.View.extend({ 
        className : 'cell', 
    
        render: function() { 
         $(this.el).data('cellId', this.model.id) 
         // I assume you're doing other render stuff here as well 
        } 
    }); 
    
    var BoardView = Backbone.View.extend({ 
        // ... 
    
        analyzeCellClick : function(evt) { 
         var cellId = $(evt.target).data('cellId'), 
          cell = this.model.cells.get(cellId); 
         // do something with cell 
        } 
    }); 
    

    Bu, belki biraz daha temiz, ama her iki şekilde çalışır düşünüyorum.

+0

OP. Her iki çözüm de kusursuz çalıştı ... ve # 1 benim amacım için mükemmel. çok teşekkürler. –

+0

Büyük - Eğer cevap mutluysan, sen skor altında onay kutusunu :) tıklayarak kabul edebilirsiniz. – nrabinowitz

+6

Çözüm 2, bence, iyi bir fikir değil. Omurga bütün mesele sunucudan veri almak ve istemci görünümünde işlemek ve görünümden verileri almak ve geri göndermek için getirmemektir. Çalışıyor, ama güzel bir yol değil. – sntran

12

İyi soru! Bence en iyi çözüm uygulamanın farklı alanları arasında tüm olayları koordine etmek bir

EventBus aka

EventDispatcher'ı uygulamak olacağını düşünüyorum. Bu rota Going

, gevşek bağlı, temiz uygulanması kolay, uzatılabilir görünüyor ve aslında, bkz omurga belgeler ile sürülmektedir Backbone Docs

da konuyla here ve here (denedim çünkü rağmen daha okuyunuz sert) kendi açıklamam bana göre sıradan görünüyor.

Beş adım açıklama:

  1. bir util olarak başka bir yerde senin ana veya bir EventBus oluşturun ve içerme/o

    var dispatcher = _.clone(Backbone.Events); // or _.extends 
    
  2. bir veya daha fazla geri arama hanlder ekle gerektirir buna (ler)

    dispatcher.CELL_CLICK = 'cellClicked' 
    
  3. (burada: CellView) sizin childView ait EventListener için bir tetikleyici ekleyin parentView ınitialize işleve bir İşleyici'yi ekleyin

    dispatcher.trigger(dispatcher.CELL_CLICK , this.model); 
    
  4. (burada: BoardView)

    eventBus.on(eventBus.CARD_CLICK, this.cardClick); 
    
  5. senin parentView ait dahilinde gelen geri arama tanımlayın (ve _.bindAll eklemek)

    cellClicked: function(model) { 
    // do what you want with your data here 
    console.log(model.get('someFnOrAttribute') 
    } 
    
6

Ben CellView click olayına izin verir, ama sadece tetik olacak bir Omurga olay: burada

var CellView = Backbone.View.extend({ 
    className : 'cell', 

    initialize: function() { 
     _.bindAll(this, 'analyzeCellClick'); 
    } 

    events : { 
     'click' : 'analyzeCellClick', 
    }, 

    analyzeCellClick : function() { 
     this.trigger('cellClicked', this.model); 
    } 
}); 

var BoardView = Backbone.View.extend({ 
    // ... 

    addCell : function(cell) { 
     var view = new Views.CellView({ 
      model : cell 
     }).render(); 

     this.cellList.append(view.el); 
     view.bind('cellClicked', function(cell) { 
       this.analyzeCellClick(cell); 
      }; 
    }, 

    analyzeCellClick : function(cell) { 
     // do something with cell 
    } 
}); 
+1

Güzel bir çözüm.Ancak kodunuzda birkaç hata var. 1. view.bind 2. Sadece biz analyzeCellClick olsun bağlamı denemek (this.analyzeCellClick 'cellClicked'). Bu yöntem, hücre görünümü tarafından tetiklendiğinden, bu nedenle görünecektir. Bu nedenle, daha çok kapatma kullanır veya Function.bind işlevini kullanır. – sachinjain024

+0

Teşekkür ederim @blunderboy! – sntran

+0

bu yaklaşım i Backbone çalışmak gerekiyordu anlamak nasıl daha tutarlı görünüyor. ya da yanlış mıyım? –