Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom components with multiple yield-like sections

I'm trying to create an ember.js component which contains multiple content sections. The intuitive way to express the desire is to use semantic sub-components which will later be rendered in appropriate places so that, e.g.

{{data-table …}}
  {{column name="Name" … }}}
    item.name
  {{/column}}
  ...
{{/data-table}}

will transform to

<table …>
  <thead>
    <th>Name</th>
    ...
  </thead>
  <tbody>
    <tr>
      <td>First item name</td>
      …
    </tr>
    ...
  </tbody>
</table>

Is it possible to implement such constructs in handlebars.js or ember.js, e.g. via handlebars helpers? If so than how?

like image 659
roman Avatar asked Dec 30 '13 14:12

roman


People also ask

What does yield do in Ember?

The natural use for {{yield}} is to decorate a template block with some HTML. Note that, using this trick, you can pass multiple blocks into a component and yield them in different parts of the component's HTML.

What is outlet in Ember JS?

Here is the explanation: {{outlet}} -> This will provide a stub/hook/point into which you can render Components(Controller + View). One would use this with the render method of routes. In your case you will likely have a details route which could look like this.


1 Answers

One way to solve this is to use multiple handlebars helpers for each of the 'sub-components' that you want.

So here is the way I would structure the app:

  • In your app/components directory add your data-table.js file
  • In your app/templates/components directory add your data-table.hbs file
  • In your app/helpers directory add a file for custom views called custom_views.js

Wherever you call your component, you can pass it parameters, these are probably from your model/controller, something along the lines of:

{{ data-table items=itemsArrayFromController }}

Now the variable itemsArrayFromController will be available to your components scope (ie in both the data-table.js file and data-table.hbs file)

In your data-table.js file you can also specify additional variables that your component has access to, so you might want to do something like:

App.DataTableComponent = Ember.Component.extend({
  headers: ['Name', 'Some other Property']
});

Then in your data-table.hbs file you can render the html for your component and use helpers to render specific parts of the component:

<table>
{{ dataTableHeaderHelper headers }}
  <tbody>
  {{#each itemsArrayFromController }}
    {{ dataTableRowsHelper item }}
  {{/each }}
  </tbody>
</table>

So here we are using the dataTableHeaderHelper to render the table header and then we loop through each item from the items array and render a row for it.

The actual table is then generated from within your helpers. So in your custom_views.js folder you can do the following:

// Returns the html for a table header
Ember.Handlebars.helper('dataTableHeaderHelper' function(headers) {
  var html = "<thead><tr>";
  for (var i = 0; i < headers.length; i++) {
    html += "<th>" + Handlebars.Utils.escapeExpression(header[i]) + "</th>";
  }
  var html += "</tr></thead>";
  return new Handlebars.Safestring(html);
}); 

// Returns the HTML for a table row
Ember.Handlebars.helper('dataTableRowsHelper' function(rows) {
  // Okay I think you get the hang of it, loop through each row
  // and then for each item generate the table row HTML
});

This should work for you!

like image 154
alalani Avatar answered Sep 18 '22 23:09

alalani