2012-07-13 30 views
8

Cho một trang sử dụng Backbone.js để có một Bộ sưu tập được gắn với Chế độ xem (RowsView, tạo ra một <ul>) tạo Chế độ xem phụ (RowView, tạo <li>) cho mỗi Mô hình trong bộ sưu tập, tôi gặp sự cố khi thiết lập chỉnh sửa nội tuyến cho các mô hình đó trong bộ sưu tập.Tìm Chế độ xem Backbone.js nếu bạn biết Mô hình?

Tôi tạo ra một phương pháp edit() trên quan điểm RowView thay thế các nội dung li với một hộp văn bản, và nếu người dùng nhấn tab trong khi đó hộp văn bản, tôi muốn kích hoạt các phương pháp edit() của Xem tiếp theo trong danh sách.

Tôi có thể lấy mô hình của mô hình tiếp theo trong bộ sưu tập:

// within a RowView 'keydown' event handler 
var myIndex = this.model.collection.indexOf(this.model); 
var nextModel = this.model.collection.at(myIndex+1); 

Nhưng câu hỏi là, làm thế nào để tìm ra Xem được gắn liền với mô hình đó. Chế độ xem phụ huynh RowsView không giữ tham chiếu đến tất cả các Chế độ xem của trẻ em; nó render() phương pháp chỉ là:

this.$el.html(''); // Clear 
this.model.each(function (model) { 
    this.$el.append(new RowView({ model:model}).render().el); 
}, this); 

Tôi có cần phải viết lại nó để giữ một mảng riêng biệt của con trỏ đến tất cả các RowView là nó có theo nó? Hoặc là có một cách thông minh để tìm xem có một mô hình được biết đến gắn liền với nó?

Dưới đây là một jsFiddle của toàn bộ vấn đề: http://jsfiddle.net/midnightlightning/G4NeJ/

Trả lời

11

Nó không phải là thanh lịch để lưu trữ một tham chiếu đến Xem trong mô hình của bạn, tuy nhiên bạn có thể liên kết một View với một mô hình với các sự kiện, làm điều này:

// within a RowView 'keydown' event handler 
var myIndex = this.model.collection.indexOf(this.model); 
var nextModel = this.model.collection.at(myIndex+1); 
nextModel.trigger('prepareEdit'); 

trong RowView lắng nghe những sự kiện prepareEdit và trong đó kêu gọi người nghe chỉnh sửa(), một cái gì đó như thế này:

this.model.on('prepareEdit', this.edit); 
2

tôi muốn nói rằngcủa bạnnên theo dõi thành phần của nó RowView s. Các cá nhân RowView s thực sự là một phần của RowsView và nó có ý nghĩa rằng một cái nhìn nên theo dõi các bộ phận của nó.

Vì vậy, RowsView của bạn sẽ có một phương pháp render loại như thế này:

render: function() { 
    this.child_views = this.collection.map(function(m) { 
     var v = new RowView({ model: m }); 
     this.$el.append(v.render().el); 
     return v; 
    }, this); 
    return this; 
} 

Sau đó, bạn chỉ cần một cách để chuyển đổi một Tab đến một chỉ mục trong this.child_views.


Một cách là sử dụng các sự kiện, quan điểm Backbone có Backbone.Events hỗn hợp trong rất quan điểm có thể kích hoạt sự kiện trên bản thân và những thứ khác có thể nghe những sự kiện đó.Trong bạn RowView bạn có thể có điều này:

events: { 
    'keydown input': 'tab_next' 
}, 
tab_next: function(e) { 
    if(e.keyCode != 9) 
     return true; 
    this.trigger('tab-next', this); 
    return false; 
} 

và bạn RowsView sẽ v.on('tab-next', this.edit_next); trong this.collection.map và bạn có thể có một loại edit_next như thế này:

edit_next: function(v) { 
    var i = this.collection.indexOf(v.model) + 1; 
    if(i >= this.collection.length) 
     i = 0; 
    this.child_views[i].enter_edit_mode(); // This method enables the <input> 
} 

Demo: http://jsfiddle.net/ambiguous/WeCRW/

Một biến thể trên điều này sẽ là thêm một tham chiếu đến số RowsView vào số RowView và sau đó tab_next có thể trực tiếp hãy gọi this.parent_view.edit_next().


Một tùy chọn khác là đặt trình xử lý keydown bên trong RowsView. Điều này thêm một chút khớp nối giữa RowViewRowsView nhưng đó có lẽ không phải là một vấn đề lớn trong trường hợp này nhưng nó là một chút xấu xí hơn các giải pháp kiện:

var RowsView = Backbone.View.extend({ 
    //... 
    events: { 
     'keydown input': 'tab_next' 
    }, 
    render: function() { 
     this.child_views = this.collection.map(function(m, i) { 
      var v = new RowView({ model: m }); 
      this.$el.append(v.render().el); 
      v.$el.data('model-index', i); // You could look at the siblings instead... 
      return v; 
     }, this); 
     return this; 
    }, 
    tab_next: function(e) { 
     if(e.keyCode != 9) 
      return true; 
     var i = $(e.target).closest('li').data('model-index') + 1; 
     if(i >= this.collection.length) 
      i = 0; 
     this.child_views[i].enter_edit_mode(); 
     return false; 
    } 
}); 

Demo: http://jsfiddle.net/ambiguous/ZnxZv/

Các vấn đề liên quan