2012-01-11 16 views
5

के साथ रनटाइम पर गतिशील रूप से एक दृश्य चुनना मैं विभिन्न प्रकार के मॉडल के साथ एक समयरेखा प्रदर्शित करने के लिए एम्बर, एम्बर डेटा और हैंडलबार्स का उपयोग कर रहा हूं। मेरा वर्तमान कार्यान्वयन, हालांकि ठीक से काम कर रहा है, ऐसा लगता है कि इसे एक सम्मेलन और सहायक के साथ काफी सुधार किया जा सकता है। हालांकि, मैं यह नहीं समझ सकता कि पहले से परिभाषित टेम्पलेट का उपयोग कैसे किया जाए।एम्बर + हैंडलबार्स

यह है कि मैं क्या है:

{{#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}} 

... एक सहायक के साथ-साथ ...

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

मैं नहीं बल्कि क्या रेंडर करने के लिए देखने यह पता लगाने की कुछ सम्मेलन पर भरोसा करेंगे। उदाहरण के लिए:

<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> 

शायद डेटा मॉडल विशेषता निर्धारित करने के लिए कैसे एक वस्तु प्रदान की गई है इस्तेमाल किया जा सकता।

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

ओह, मैं समझ नहीं एक सहायक से खाका तक पहुँच करने के लिए कैसे।

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

इसके अलावा, क्या मुझे हैंडलबार्स के साथ कुछ करना है?

उत्तर

1

यह मेरे सिर के शीर्ष से बाहर है: मैं प्रत्येक मॉडल प्रकार के लिए एक अलग टेम्पलेट/दृश्य तैयार करूंगा। जैसे होगा एक DesignView, OrderView, आदि इनमें से प्रत्येक TEMPLATENAME (सभी कोड coffeescript) के साथ उपयोग करने के लिए टेम्पलेट में निर्दिष्ट करना होगा:

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

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

प्रत्येक प्रकार के लिए कस्टम प्रतिपादन के सभी देखें/टेम्पलेट के अंदर की जाएगी ।

इस बिंदु पर हमें प्रत्येक आइटम के लिए कौन सा दृश्य दिखाना है यह तय करने के लिए कुछ टेम्पलेट तर्क होना चाहिए। सबसे आसान करने के लिए चीज मॉडल पर व्यू टाइप को स्टोर करना होगा।

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

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

फिर टेम्पलेट दिखाई दे सकता है जैसे:

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

यह आदर्श नहीं है, हालांकि, क्योंकि हम मॉडल दृश्य परत के बारे में पता करने के लिए नहीं करना चाहती। इसके बजाय, हम मॉडल के लिए दृश्य बनाने के लिए कुछ फैक्ट्री तर्क बना सकते हैं।

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') 

टेम्पलेट तो इस प्रकार दिखाई देगा:

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

को शायद बेहतर तरीके हैं तब हम जो मॉडल की एक सरणी और उनके इसी विचारों शामिल नियंत्रक पर एक गणना संपत्ति बना सकते हैं यह करो। मुझे एम्बर के मूल के करीब होने वाले किसी व्यक्ति को सुनना अच्छा लगेगा।

http://jsfiddle.net/rsaccon/AD2RY/

5

उपयोग ViewStates, पर उदाहरण देखें। एक मॉडल एक समान नाम के साथ एक दृश्य के अनुरूप है। उदाहरण के लिए, एक ऐप।डिज़ाइन मॉडल उदाहरण दृश्य App.DesignView के अनुरूप है।

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

मैं अपने मॉडल में इस मिश्रण ...

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

... और इस तरह एक मिश्रित संग्रह से अधिक पुनरावृति:

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

इस तरह, मैं सम्मेलन को परिभाषित करने से बचें स्पष्ट रूप से मेरे मॉडल में। गॉर्डन के लिए धन्यवाद, मुझे एहसास हुआ कि दृश्य किसी ऑब्जेक्ट पर किसी संपत्ति का उपयोग करके निर्दिष्ट किया जा सकता है। मैं अभी भी इस समस्या को हल करने के 'सही' तरीके के बारे में सुनना चाहूंगा।

4

मैं एक mixin का उपयोग कर अपने ही सम्मेलन की स्थापना से इस हल:

1

यही वह है जो मैंने इसी तरह के परिदृश्य के लिए उपयोग किया था।

मॉडल 'पेज' में कई 'गतिविधि' है।

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

मॉडल 'गतिविधि' संपत्ति 'प्रकार' कि संदर्भ जो टेम्पलेट एक और संपत्ति 'विन्यास' में सामग्री के लिए उपयोग करने के लिए है।

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

कॉन्फ़िगरेशन के लिए विशेषता प्रकार की कमी पर ध्यान दें। यह यादृच्छिक रूप से संरचित वस्तुओं के संग्रह को संग्रहीत करने के साधन प्रदान करता है। लगातार संरचित वस्तुओं के लिए, मैं Ember-Data.Model-Fragments का उपयोग करने का सुझाव देता हूं।

मुख्य टेम्पलेट:

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

प्रकार के लिए: 'स्थिर' है, यह का उपयोग करता है {{{3 मूंछें विकल्प}}} एक एचटीएमएल स्ट्रिंग रेंडर करने।

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

अन्य विकल्प कहीं अधिक जटिल हैं, फिर भी 'साथ' का उपयोग करके सरलीकृत हैं। अर्थात्: प्रकार के लिए: '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}} 
partials साथ

, नामकरण और/या फ़ोल्डर संरचना अपने परिवेश के आधार पर, यानी '_partialname.hbs' या विचार करने के लिए याद 'VIEWNAME/partialname.hbs'

संबंधित मुद्दे