2012-01-11 14 views
5

Tôi đang sử dụng Ember, Ember Data và Handlebars để hiển thị dòng thời gian với một số loại mô hình khác nhau. Thực hiện hiện tại của tôi, mặc dù hoạt động đúng, có vẻ như nó có thể được cải thiện đáng kể với một quy ước và một người trợ giúp. Tuy nhiên, tôi không thể tìm ra cách sử dụng các mẫu đã được xác định.Tự động chọn chế độ xem khi chạy với Ember + Handlebars

Đây là những gì tôi có:

{{#view App.AccountSelectedView contentBinding="App.selectedAccountController.everythingSorted"}} 
    {{#with content}} 
    <ol class="timeline"> 
     {{#each this}} 
     {{#is constructor="App.Design"}} 
     ... stuff about the design 
     {{/is}} 
     {{#is constructor="App.Order"}} 
     ... stuff about the order 
     {{/is}} 
     {{#is constructor="App.Message"}} 
     ... stuff about the message 
     {{/is}} 
     {{/each}} 
    </ol> 
    {{/with}} 
{{/view}} 

... cùng với một helper ...

Handlebars.registerHelper('is', function(options) { 
    if (this.constructor == options.hash["constructor"]) { 
    return options.fn(this); 
    } 
}); 

Tôi thà dựa vào một số ước để tìm ra những gì xem để render. Ví dụ:

<script type="text/x-handlebars-template" data-model="App.Design" id="design-view"> 
... stuff about the design 
</script> 

<script type="text/x-handlebars-template" data-model="App.Order" id="order-view"> 
... stuff about the order 
</script> 

Có thể sử dụng thuộc tính mô hình dữ liệu để xác định cách đối tượng được hiển thị.

{{#view App.SelectedAccountView contentBinding="App.selectedAccountController.everythingSorted"}} 
    {{#with content}} 
    <ol class="timeline"> 
     {{#each this}} 
     {{viewish this}} 
     {{/each}} 
    </ol> 
    {{/with}} 
{{/view}} 

Than ôi, tôi không thể tìm ra cách truy cập các mẫu từ trình trợ giúp.

Handlebars.registerHelper('viewish', function(options) { 
    // Were I able to access the templates this question 
    // would be unnecessary. 
    // Handlebars.TEMPLATES is undefined... 
}); 

Ngoài ra, đây có phải là điều tôi nên làm với Handlebars không?

Trả lời

1

Đây chỉ là phần trên đầu của tôi: Tôi sẽ tạo mẫu/chế độ xem riêng cho từng loại mô hình. Ví dụ. sẽ có một DesignView, OrderView, vv Mỗi trong số này sẽ xác định các mẫu để sử dụng với TEMPLATENAME (tất cả các mã coffeescript):

App.DesignView = Em.View.extend 
    templateName: 'design' 

App.OrderView = Em.View.extend 
    templateName: 'order' 

Tất cả các hiển thị tùy chỉnh cho từng loại sẽ được thực hiện bên trong xem/mẫu .

Tại thời điểm này, chúng tôi cần có một số logic mẫu để quyết định chế độ xem nào sẽ hiển thị cho từng mục. dễ nhất điều cần làm là lưu trữ loại xem trên mô hình.

App.Design = Em.Model.extend 
    viewType: App.DesignView 

App.Order = Em.Model.extend 
    viewType: App.OrderView 

Sau đó mẫu có thể trông giống như:

{{#collection contentBinding="App.selectedAccountController.everythingSorted"}} 
    {{view content.viewType contentBinding="content"}} 
{{/collection}} 

Đây không phải là lý tưởng, tuy nhiên, vì chúng tôi không muốn các mô hình để biết về các lớp xem. Thay vào đó, chúng ta có thể tạo ra một số logic nhà máy để tạo ra một khung nhìn cho một mô hình. Sau đó chúng ta có thể tạo ra một tài sản tính trên bộ điều khiển, trong đó có một mảng của các mô hình và quan điểm tương ứng của họ:

App.selectedAccountController = Em.ArrayController.create 
    .. 
    viewForModel: (model) -> 
    # if model is instance of Design return DesignView, Order return OrderView etc. 
    everythingSortedWithViews: (-> 
    everythingSorted.map (model) -> 
     {model: model, viewType: @viewForModel(model)} 
).property('everythingSorted') 

Mẫu sau đó sẽ trông như thế này:

{{#collection contentBinding="App.selectedAccountController.everythingSortedWithView"}} 
    {{view content.viewType contentBinding="content.model"}} 
{{/collection}} 

Có nhiều cách có thể tốt hơn để làm cái này. Tôi rất thích nghe một người gần gũi hơn với cốt lõi của Ember đưa ra một giải pháp.

4

tôi giải quyết điều này bằng cách xây dựng ước của riêng tôi sử dụng một mixin. Mô hình tương ứng với chế độ xem có tên tương tự. Ví dụ: một ứng dụng.Ví dụ mô hình thiết kế tương ứng với khung nhìn App.DesignView.

App.ViewTypeConvention = Ember.Mixin.create({ 
    viewType: function() { 
    return Em.getPath(this.get('constructor') + 'View'); 
    }.property().cacheable() 
}); 

Tôi trộn này vào mô hình của tôi ...

App.Design.reopen(App.ViewTypeConvention); 
App.Order.reopen(App.ViewTypeConvention); 

... và duyệt qua một tập hợp hỗn hợp như thế này:

{{#each content}} 
    {{view item.viewType tagName="li" contentBinding="this"}} 
{{/each}} 

Bằng cách này, tôi tránh định ước một cách rõ ràng trong các mô hình của tôi. Nhờ Gordon, tôi nhận ra rằng khung nhìn có thể được xác định bằng cách sử dụng một thuộc tính trên một đối tượng. Tôi vẫn thực sự muốn nghe về cách 'đúng' để giải quyết vấn đề này.

1

Đây là những gì tôi đã sử dụng cho một kịch bản tương tự.

Trang 'Mô hình' có hoạt động 'Nhiều'.

// App.PageModel 
export default DS.Model.extend({ 
    index  : DS.attr('number'), 
    activity : DS.hasMany('activity', { async: true }) 
}); 

Mô hình 'hoạt động' có thuộc tính 'tham chiếu mẫu để sử dụng cho nội dung trong cấu hình thuộc tính khác'.

// App.ActivityModel 
export default DS.Model.extend({ 
    activityId : DS.attr('string'), 
    type   : DS.attr('string'), 
    page   : DS.belongsTo('page', { async: true }), 
    configuration : DS.attr() 
}); 

Lưu ý việc thiếu loại thuộc tính để định cấu hình. Điều này cung cấp các phương tiện lưu trữ một tập hợp các đối tượng có cấu trúc ngẫu nhiên. Đối với các đối tượng có cấu trúc nhất quán, tôi khuyên bạn nên sử dụng Ember-Data.Model-Fragments.

mẫu chính:

{{! page.hbs }} 
{{#with activity}} 
    {{#each}} 
     {{partial type}} 
    {{/each}} 
{{/with}} 

Đối với loại: 'tĩnh', nó sử dụng {{{3 tùy chọn bộ ria mép}}} để render một chuỗi html.

{{! static.hbs }} 
{{{configuration.content}}} 

Các tùy chọn khác phức tạp hơn nhiều, nhưng vẫn đơn giản bằng cách sử dụng 'có'. ví dụ: cho loại hình: 'multiplechoice',

{{! multiplechoice.hbs }} 
{{#with configuration}} 
    {{#each options}} 
    <label {{bind-attr class=":label selected:checked:unchecked"}}> 
     {{view Ember.Checkbox checkedBinding="selected" }} 
     {{#if text.content}} 
      {{{text.content}}} 
     {{else}} 
      {{text}} 
     {{/if}} 
    </label> 
    {{/each}} 
    {{ ...etc... }} 
{{/with}} 

Với partials, hãy nhớ xem xét danh pháp và/hoặc cấu trúc thư mục tùy thuộc vào môi trường của bạn, ví dụ: '_partialname.hbs' hoặc 'viewname/partialname.hbs'

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