Passing Data Back to Components - ember.js

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

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

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/

How to render controller without container tag in table?

I have really enormous table to handle in Ember.js. At this moment I am using to this job single controller, but it breaks single responsibility principle.
<table>
<thead>
<tr>
<th>First column in first group</th>
<th>Second column in first group</th>
<th>First column in second group</th>
<th>Second column in second group</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{controller.someAction}}</td>
<td>{{controller.otherAction}}</td>
<td>{{controller.someAction2}}</td>
<td>{{controller.otherAction2}}</td>
</tr>
</tbody>
</table>
Instead I would like to group couples of related actions in one controller.
<table>
<thead>
<tr>
<th>First column in first group</th>
<th>Second column in first group</th>
<th>First column in second group</th>
<th>Second column in second group</th>
</tr>
</thead>
<tbody>
<tr>
{{render 'firstGroup' this}}
{{render 'secondGroup' this}}
</tr>
</tbody>
</table>
However, it is not going to work. Ember will place firstGroup in some kind of tag (for instance div), which can't be located directly beetwen <tr> and <td>. I can't use neither <tr>, nor <td> for rendering container.
It would be great if ember could render controller without container's tag. Is there any way to deal with that? Maybe there is special tag in HTML which won't breake my table layout and can be placed in that position? "Actions" in my controller are only calculating values based on model. Maybe Should I use something other than controller?
Yes and no.
You can define the tag to be used for a particular view, unfortunately having it host multiple columns using render would be difficult. So you'd likely need to break it down to individual TDs using render.
<tr>
{{render 'firstGroup' this}}
{{render 'secondGroup' this}}
{{render 'thirdGroup' this}}
{{render 'fourthGroup' this}}
</tr>
App.FirstGroupView = Em.View.extend({
tagName:'td'
});
http://emberjs.jsbin.com/jafanitu/1/edit
That being said, I'd probably break it down at the row level with render, then use partials at the column level
<tbody>
{{render 'row' this}}
</tbody>
<script type="text/x-handlebars" data-template-name="row">
{{partial 'first_group'}}
{{partial 'second_group'}}
{{partial 'third_group'}}
{{partial 'fourth_group'}}
</script>
<script type="text/x-handlebars" data-template-name="_first_group">
<td>
hello world
</td>
</script>
http://emberjs.jsbin.com/jafanitu/2/edit
And then create mixins for handling the logic of each group and add those mixins to your controller, to keep your controller clean. http://emberjs.com/api/classes/Ember.Mixin.html
You can pass parameters to the view being rendered by the {{render}} helper:
{{render "myView" someViewProperty="foo" anotherViewProperty=4}}
Therefore you can set the tagName of your views, so that you get the correct HTML structure:
<table>
<thead>
<tr>
<th>First column in first group</th>
<th>Second column in first group</th>
<th>First column in second group</th>
<th>Second column in second group</th>
</tr>
</thead>
<tbody>
<tr>
{{render 'firstGroup' this tagName="td"}}
{{render 'secondGroup' this tagName="td"}}
</tr>
</tbody>
</table>

Ember Data Access App initialization

at the moment im really frustrated. I ll try to get table filled with some data of my database. Therefore i have a controller and a View.
App.TableController.extend({
content: [],
contentBinding:'App.incidient.content'
})
App.TableView = Ember.CollectionView.extend({
tagName: 'tbody',
itemViewClass: Ember.View.extend({
templateName: 'table'
})
My html code looks like this:
<div class="row-fluid">
<table class="table table-striped">
<thead>
<tr>
<th>
Title
</th>
<th>
Customer
</th>
<th>
Machine
</th>
<th>
Priortity
</th>
<th>
Status
</th>
</tr>
<thead>
{{view App.TableView}}
</table>
</div>
</script>
<script type="text/x-handlebars" data-template-name="table">
{{#each item in content}}
<td>
{{view item.incidient.title}}
</td>
<td>
{{view item.incidient.customer}}
</td>
<td>
{{view item.incidient.machine}}
</td>
<td>
{{view item.incidient.priority}}
</td>
<td>
{{view item.incidient.status}}
</td>
{{/each}}
</script>
Im not frustrated because of my the code that is not working. It is more about the fact that:
i dont find any good guide or post where i can see how to debug my Application. The Debugging tool from Chrome doesnt help at all, because i can't figure out how to get access to the content of my TableController or better where i can find it.
i dont understand where the App is initializing all of my Controllers and how i can access them. With the old router: it was like 'App.router.myController' but this is not working anymore.
i dont know how to access datas from a different controller. I tried to bind the Table.Controller.content to the 'App.incidient.content' and Ember didnt even throw an exception or something
I hope you can help. I dont think that these question are really difficult to answer but for a noobie like me they are quite fundamental.
Greeting and thank you
Alex