Ember.js / Handlebars nested each iterations - ember.js

Having a view that should represent a table, having columns and rows:
App.ListView = Ember.View.extend({
templateName: 'list',
columns: ['t1', 't2', 't3'],
rows: [
{ t1: 'one', t2: 'two', t3: 'three' },
{ t1: 'two', t2: 'one', t3: 'seven' }
]
});
- respectively a template:
<table>
<thead>
<tr>
{{#each columns}}
<th>{{this}}</th>
{{/each}}
</tr>
</thead>
<tbody>
{{#each rows}}
<tr>
{{#each ../columns}}
<td>does nothing: {{this}}</td>
{{/each}}
</tr>
{{/each}}
<tbody>
<table>
... which can be found on jsfiddle as well: jsfiddle.net/nWnf2
I obviously can not iterate over columns when nested in rows. {{#each ../columns}} simply is not triggered at all. Why is that? What is a better approach?

Ember doesn't really support the file path identifiers from Handlebars. You can however access via view.columns.
<table>
<thead>
<tr>
{{#each columns}}
<th>{{this}}</th>
{{/each}}
</tr>
</thead>
<tbody>
{{#each rows}}
<tr>
{{#each view.columns}}
<td>does nothing: {{this}}</td>
{{/each}}
</tr>
{{/each}}
<tbody>
<table>
http://jsfiddle.net/L7MAp/
Looking at your code snippet, I suggest you look at using {{#collection}} instead of {{#each}} as well, it won't alleviate that issue but it makes your code cleaner (IMO).

Related

How to Use Jquery Datatables in Ember 2.0

I picked up learning emberJS lately and I have had issues doing some basic things I would have done while not using this framework. The main issues I have had was using jquery plugins, in this case jquery datatables
in my component's component.js
import Ember from 'ember';
export default Ember.Component.extend({
didInsertElement: function(model){
Ember.run.scheduleOnce('afterRender', this, function(model) {
this.$(".datatables").DataTable();
});
}
});
in my component's template.hbs
<table class="table table-hover datatables">
<thead>
<tr>
<th>Course Name</th>
<th>Course Title</th>
<th class="text-center">Actions</th>
</tr>
</thead>
<tbody>
{{#each courses as |course|}}
<tr>
<td> {{ course.name }} </td>
<td> {{ course.title }} </td>
<td class="text-center"> {{#link-to 'courses.edit' course }} Edit {{/link-to}} </td>
</tr>
{{/each}}
</tbody>
</table>
**then i used the component like :- **
{{#course-datatable courses=model}}{{/course-datatable}}
I would appreciate a demo accompanied with answers.
cheers
Ok so i haven't done a component of the jquery datatable plugin. But yes for other Jquery plugins, it would be more or less like this. If you are building your own component:
Add the Datatable js files to include inside your BrocFile
Run in ember client
ember g my-jquery-datatable
this will generate the component in the generated hbs fill in the general html you would use
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
</tr>
</thead>
{{#each modelWithData}}
<tr>
<td>this.name</td>
<td>this.position</td>
</tr>
{{/each}}
</table>
then on you js generated file initiate the plugin in the didInsertElementMethod
export default Ember.Component.extend({
didInsertElement(){
this.$('#example').DataTable();
}
});
then to be able to use this table in other components or controllers you can do
{{my-jquery-datatable modelWithData=otherArrayWithTheTableAttributes}}
Hope it helps

Passing Data Back to Components

I currently have a component a couple of components. One is a component to display all my table view data, and inside of that component, is another to display the search fields. They look like so:
{{#table-display model=model}}
<table class="data-table">
<thead>
<tr>
<th>Status</th>
<th>Name</th>
<th>Email Address</th>
</tr>
</thead>
<tbody>
{{#each filteredModel as |contact| }}
{{#link-to 'contacts.edit' contact tagName="tr"}}
<td>{{ current-status model=contact }}</td>
<td>{{ contact.name }}</td>
<td><em>{{ contact.name }}</em></td>
<td><em>{{ contact.email }}</em></td>
{{/link-to}}
{{/each}}
</tbody>
</table>
{{/table-display}}
Then inside of the table-display component, I have my search filter input.
{{input value=filterString placeholder="Search Contacts" }}
The table filtering works if I put the table into the table-display component, but not if it's just within the component. What am I doing wrong here?
There is a few ways to get the fitleredModel data to flow out of the component, the idiomatic way is to use HTMLBars blocked params.
Inside table-display's template:
...
{{input value=filterString placeholder="Search Contacts" }}
...
{{yield filteredModel}}
And then in your main template:
{{#table-display model=model as |filteredModel|}}
...
{{#each filteredModel as |contact|}}
...
{{/each}}
{{/table-display}}

Link-to the previous nested resource in ember

Router.map(function() {
this.resource('users', { path: '/stores/'+store_id+'/users' });
this.route('user', { path: '/stores/'+store_id+'/users/:user_id'}, function() {
this.resource('devices', { path: '/devices' });
});
});
On devices page I want to go back to /users/:user_id.
Here is my template/devices.hbs
<table>
<tr>
<th>model</th>
<th>user_id</th>
</tr>
{{#each model as |device|}}
<tr>
<td>{{device.model}}</td>
<td>{{#link-to "???" ?? ???}}{{device.user_id}}{{/link-to}}</td>
</tr>
{{/each}}
</table>
I don't how to go back to the specific resource.
Use user.index, because it's fully qualified route name with URL: /users/:user_id.
{{#link-to 'user.index'}}Go back to /users/:user_id{{/link-to}}
<table>
<tr>
<th>model</th>
<th>user_id</th>
</tr>
{{#each model as |device|}}
<tr>
<td>{{device.model}}</td>
<td>{{#link-to "???" ?? ???}}{{device.user_id}}{{/link-to}}</td>
</tr>
{{/each}}
</table>
Thanks to #daniel-kmak for the tips. The route is fully qualified at user.index
<table>
<tr>
<th>model</th>
<th>user_id</th>
</tr>
{{#each model as |device|}}
<tr>
<td>{{device.model}}</td>
<td>{{#link-to 'user.index'}}{{device.user_id}}{{/link-to}}</td>
</tr>
{{/each}}
</table>

Ember checkboxes are connected

I have a table of data. You can checkmark the rows you want to save. The problem I have is that all the checkboxes are connected. So if you check one, it checks them all and if you uncheck one then they all uncheck. Some of them come pre-checked and I'm passing in the isChecked value to indicate that. How do I make each one unique?
Template:
<table>
<thead>
<tr>
<th class="center"><br>Select<br> {{input type="checkbox" checked=allChecked}}</th>
<th class="center">
<a href="#" {{action 'sortBy' 'itemId'}} {{bind-attr class="itemId:active sortAscending:asc:desc"}}>ID</a>
</th>
<th class="">
<a href="#" {{action 'sortBy' 'description'}} {{bind-attr class="description:active sortAscending:asc:desc"}}>Item Description</a>
</th>
<th>{{!-- actions --}}</th>
</tr>
</thead>
{{#each item in pagedContent}}
<tr>
<td class="center">{{input type="checkbox" checked=isChecked name=item.itemId}}</td>
<td class="center">{{item.itemId}}</td>
<td class="">{{item.description}}</td>
</tr>
{{/each}}
</tbody>
</table>
Controller
import Ember from 'ember';
import pageableTable from 'web-app-admin/mixins/pageable-table';
export default Ember.ArrayController.extend(pageableTable, {
isChecked: true,
allChecked: true,
allCheckedToggle: function(){
if(this.get('allChecked') === false){
this.set('isChecked', false);
}
else{
this.set('isChecked', true);
}
}.observes('allChecked')
});
Template:
{{#each pagedContent key='itemId' as |item|}}
<tr>
<td class="center">{{input type="checkbox" checked=item.isChecked name=item.itemId}}</td>
<td class="center">{{item.itemId}}</td>
<td class="">{{item.description}}</td>
</tr>
{{/each}}
Controller:
import Ember from 'ember';
import pageableTable from 'web-app-admin/mixins/pageable-table';
export default Ember.ArrayController.extend(pageableTable, {
allChecked: true,
allCheckedToggle: Ember.observer('allChecked', function() {
this.get('pagedContent').forEach(function (item) {
item.set('isChecked', this.get('allChecked'));
});
})
});
And add property to item Model or object:
isChecked: true
Should work as expected.

Ember list of checkbox on check one send rest

I have a list of checkboxes in my template:
<table>
<thead>
<tr>
<th></th>
<th>Sender</th>
<th>Title</th>
</tr>
</thead>
<tbody>
{{#each message in model.entities}}
<tr>
<td class="cell-star">
{{input type="checkbox" name=message.id tabindex=message.id class="starBox" checked=message.isStar }}
</td>
<td class="cell-broadcaster">
{{message.notification.autor.firstName}} {{message.notification.autor.lastName}}
</td>
<td class="cell-title">
{{#link-to 'notifications.details' message.notification.id}}{{message.notification.title}}{{/link-to}} {{#unless message.isRead}} (new) {{/unless}}
</td>
</tr>
{{/each}}
</tbody>
</table>
And now i want to send rest query every time when i change some of the checkbox state with id of changed checkbox.
What should i write in my controller?
i have tried something like that but i cannot get data of changed checkbox:
updateStarStatus: function() {
console.log('checkbox clicked');
//here should be something like that:
//$.getJSON(apiHost + "/api/forum/star/"+id);
}.observes('model.entities.#each.isStar'),
im not using emberData. My model looks like this:
model: function() {
return $.getJSON(apiHost + "/api/forum");
},
You could use the observesBefore method to track the changes and make a diff in the observes method, but I'd rather use the native on change event, to trigger an action and pass the object:
<div {{action "updateStarStatus" message on="change"}}>
{{input type="checkbox" checked=message.isStar}}
and in the controller
actions: {
updateStarStatus: function(message) {
alert(message.id)
}
}
http://emberjs.jsbin.com/zohaqodese/2/