Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h2><a href="http://emberjs.com/api/classes/Ember.Component.html"><code>Ember.Component</code></a> is your friend</h2> <p>As @raulbrito already mentioned, the best way to go if you want reusable components in ember is indeed to use the new <code>Ember.Component</code> which is heavily based on the <a href="http://www.w3.org/TR/2013/WD-components-intro-20130606/">new w3 draft for web components</a> and thus beeing future proof.</p> <p>I've tried to make a simple example on how this could be implemented. Given a simple <code>route</code> where the <code>model</code> hook returns some static data:</p> <h3>Index Route</h3> <pre><code>App.IndexRoute = Ember.Route.extend({ model: function(){ return Ember.Object.create({ modelOne: data, modelTwo: data2 }); } }); </code></pre> <p><code>data</code> and <code>data2</code> are simply static objects globally defined for simplicity <em>(as you will see <a href="http://jsbin.com/odosoy/146/edit">in the demo</a>)</em>, but this could be also data coming from a backend or from fixtures etc.</p> <h3>Index template</h3> <p>In the template then we insert our chart component with the line <code>{{line-chart data=model.modelOne}}</code> and as you can see, we also set the <code>data</code> attribute to the index model <code>model.modelOne</code> or <code>model.modelTwo</code>:</p> <pre><code>&lt;script type="text/x-handlebars" id="index"&gt; &lt;h2&gt;Chart one&lt;/h2&gt; {{line-chart data=model.modelOne}} &lt;h2&gt;Chart two&lt;/h2&gt; {{line-chart data=model.modelTwo}} &lt;/script&gt; </code></pre> <h3>Component Template</h3> <p>Our component template looks fairly simple because it will render a simple <code>canvas</code> element, but it could be as complex as needed, on how to use <code>Ember.Component</code> please refer also to the <a href="http://emberjs.com/guides/components/">docs</a>:</p> <pre><code>&lt;script type="text/x-handlebars" id="components/line-chart"&gt; &lt;/script&gt; </code></pre> <h3>Component Subclass</h3> <pre><code>App.LineChartComponent = Ember.Component.extend({ tagName: 'canvas', attributeBindings: ['width', 'height'], width: '480', height: '360', data: null, didInsertElement: function() { var ctx = this.get('element').getContext("2d"); var myNewChart = new Chart(ctx).Line(this.get('data')); } }); </code></pre> <p>Note the naming is important here, Ember knows which subclass powers a component based on its name. For example, if you have a component called <code>line-chart</code>, you would create a subclass called <code>App.LineChartComponent</code>. If your component was called <code>bar-chart-simple</code>, the class name would be <code>App.BarChartSimpleComponent</code> and so on. Ember will look for a class with the camelized name of the component, followed by <code>Component</code>.</p> <p>So, and since <code>Ember.Component</code> extends from <code>Ember.View</code> we can define all sorts of properties <code>Ember.View</code> supports like <code>tagName</code>. In our case we use <code>canvas</code> because this is what <code>chart.js</code> needs to work. As you can see we have also defined some <code>attributeBindings</code> to control the <code>width</code> and <code>height</code> of the <code>canvas</code> from inside ember. The component has also a <code>data</code> attribute <em>(which could be called whatever you find appropriate)</em> defined on which we later set our model data in the template returned from the <code>IndexRoute</code> <code>model</code> hook. And finally in your <code>didInsertElement</code> hook of our component we initialize the chart passing with <code>this.get('data')</code> the data object to new created <code>Chart.js</code> class.</p> <pre><code>var ctx = this.get('element').getContext("2d"); var myNewChart = new Chart(ctx).Line(this.get('data')); </code></pre> <p>And last but not least, please see here for a <a href="http://jsbin.com/odosoy/146/edit">working example</a> of the above explained.</p> <p>Hope it helps.</p> <h2>Update in response to your last comment</h2> <p>I've tried to simulate a delay in the resolution of the <code>model</code> hook to mimic a response from a backend, as you can see the template rendering is waiting for the <code>model</code> promise to resolve first. Basically what I've done is to use <code>Ember.run.later</code> with a delay of 2000ms that resolves the promise once timed out:</p> <pre><code>App.IndexRoute = Ember.Route.extend({ model: function(){ return new Ember.RSVP.Promise(function(resolve) { Ember.run.later(function() { var m = Ember.Object.create({ modelOne: data, modelTwo: data2 }); resolve(m); }, 2000); }); } }); </code></pre> <p>And just for fun I've also added a <code>LoadingRoute</code> to show a spinner while the promise resolution is waiting for data, the <code>LoadingRoute</code> is a less documented feature of ember, you can read more about it here: <a href="https://gist.github.com/machty/5647589">https://gist.github.com/machty/5647589</a> under <em>How do I put up a (global) Loading Spinner during a transition w/ Promises?</em></p> <p>Plase see here for a updated example: <a href="http://jsbin.com/odosoy/145/edit">http://jsbin.com/odosoy/145/edit</a></p> <h2>Update in response to @SamSelikoff's comment</h2> <p>As for the above mentioned <code>LoadingRoute</code> @SamSelikoff pointed out that it's officially documented now: <a href="http://emberjs.com/guides/routing/defining-your-routes/#toc_initial-routes">http://emberjs.com/guides/routing/defining-your-routes/#toc_initial-routes</a></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload