Ember.JS - toggleProperty toggling all items in list - ember.js

I have a toggleProperty in the container to toggle a set of actions on each item. The problem is, when the toggle button on 1 item is clicked, every item is toggled, instead of the one that's clicked.
I would love to know how to toggle only the clicked item, not everything from the list.
I am using the ember-cli to build my application.
My category model:
import DS from 'ember-data';
export default DS.Model.extend({
pk: DS.attr('string'),
category: DS.attr('string'),
products: DS.hasMany('product'),
});
My category route:
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.findAll('category');
},
});
My category controller
expand: function() {
this.toggleProperty('isExpanded', true);
}
My template:
{{#each model as |i|}}
<tr>
<td>
<a {{action 'expand'}}>{{i.category}}</a>
</td>
<td>
{{i.pk}}
</td>
<td>
{{#if isExpanded}}
<button {{action "deleteCategory"}}>Edit</button>
<button {{action "deleteCategory"}}>Delete</button>
{{else}}
<button {{action 'expand'}}>Actions</button>
{{/if}}
</td>
</tr>
{{/each}}
Since stackoverflow, is not letting me post without adding more text, I would also like to know how to show all the products associated with the category, on the same route (same page), by clicking on each category?
Cheers and thank you.

In controller:
expand(item) {
if (!item) {
return;
}
item.toggleProperty('isExpanded', true);
}
Template:
{{#each model as |i|}}
<tr>
<td>
<a {{action 'expand' i}}>{{i.category}}</a>
</td>
<td>
{{i.pk}}
</td>
<td>
{{#if i.isExpanded}}
<button {{action "deleteCategory"}}>Edit</button>
<button {{action "deleteCategory"}}>Delete</button>
Products:
{{#each i.products as |product|}}
{{product}}
{{/each}}
{{else}}
<button {{action 'expand' i}}>Actions</button>
{{/if}}
</td>
</tr>
{{/each}}

Related

ember link-to from the component

i am new at EmberJs.
I tried to link from the component "invoices-list" to invoice.
invoices-list.hbs
{{#each invoices as |invoice|}}
<tr>
<td>{{invoice.kdnr}}</td>
<td>{{invoice.rnr}}</td>
<td>{{invoice.invoiceId}}</td>
<td>**{{#link-to 'invoice' invoice.invoiceId}}Click here{{/link-to}}**</td>
</tr>
{{else}}
<p>No datas</p>
{{/each}}
invoices.hbs
{{invoices-list invoices=model}}
router.js
Router.map(function() {
this.route('invoices');
this.route('invoice', { path: '/invoice/:invoice_id' });
});
My problem is, the template will not rendered and i get the error: "props.parentView.appendChild is not a function"
What is wrong?
Thanks for help.
Fabian
Let me give you first an example how to use Link-to
Suppose this is your Route.js
Router.map(function() {
this.route('photos', function(){
this.route('edit', { path: '/:photo_id' });
});
});
and this is app/templates/photos.hbs
<ul>
{{#each photos as |photo|}}
<li>{{#link-to "photos.edit" photo}}{{photo.title}}{{/link-to}}</li>
{{/each}}
</ul>
then rendered HTML would be
<ul>
<li>Happy Kittens</li>
<li>Puppy Running</li>
<li>Mountain Landscape</li>
</ul>
so in your case this is Route
Router.map(function() {
this.route('invoices');
this.route('invoice', { path: '/invoice/:invoice_id' });
});
then you may use this
{{#each invoices as |invoice|}}
<tr>
<td>{{invoice.kdnr}}</td>
<td>{{invoice.rnr}}</td>
<td>{{#link-to 'invoice' invoice}}{{/link-to}}</td>
</tr>
{{else}}
<p>No datas</p>
{{/each}}
another example to clarify:
//Route.js
this.route('contacts');
this.route('contact', { path: 'contacts/:contact_id' });
//Contacts.hbs
{{#each model as |contact|}}
<tr>
<td>{{link-to contact.name 'contact' contact}}</td>
<td>{{link-to contact.email 'contact' contact}}</td>
<td>{{contact.country}}</td>
</tr>
{{/each}}
Hope it works for you. more info.

How to use handlebars 'if' with emberjs model data

Iam having a table using bootstrap components with each row clickable
am also using handlebars inside table rows
<tbody data-link="row" class="rowlink">
{{#each model.pastreqlist}}
{{#if_eq {{status}} "PENDING"}}
<tr data-toggle="modal" data-target="#pastreq {{action "selectRow" this target="view"}}">
{{else}}
<tr>
{{/if_eq}}
<td>{{employee_name}}</td>
<td>{{type_id}}</td>
<td>{{from_date}}</td>
</tr>
{{/each}}
</tbody>
i want to enable the content inside tr i.e i want to pop up modal for only those rows which is having status as "PENDING"
so far i have tried this but its not working
here's my helper code also
Handlebars.registerHelper('if_eq', function(a, b, opts) {
if(a == b)
return opts.fn(this);
else
return opts.inverse(this);
});
here is my controller code
App.LinksController = Ember.ObjectController.extend({
actions: {
myleavesinfolist: function () {
rdata = $.ajax({
type: "POST",
url: "/myleaves",
dataType: "json",
async: false
}).responseJSON;
this.transitionToRoute("myleaves", rdata);
} //myleavesinfolist
} //actions
}); //controller
please help am a newbie to handlebars and ember js
i used handlebars registerhelper in my script as below
Ember.Handlebars.registerHelper('ifeq', function(a, b, options) {
return Ember.Handlebars.bind.call(options.contexts[0], a, options, true, function(result) {
return result === b;
});
});
and in my template i have done like this
{{#each model.pastreqlist}}
{{#ifeq status "PENDING"}}
<tr data-toggle="modal" data-target="#pastrequestsmodal" {{action "selectRow" this target="view"}} style="cursor: pointer">
{{else}}
<tr>
{{/ifeq}}
You should set up a computer property on your model, like this:
App.Request = Ember.Model.extend({
stats:DS.attr('string'),
isPending:function(){
if(this.get('status') === 'PENDING'){
return true;
}
}.property('status')
});
Then in your template, you can do it like this:
<tbody data-link="row" class="rowlink">
{{#each model.pastreqlist}}
{{#if isPending}}
<tr data-toggle="modal" data-target="#pastreq" {{action "selectRow" this target="view"}}>
{{else}}
<tr>
{{/if}}
<td>{{employee_name}}</td>
<td>{{type_id}}</td>
<td>{{from_date}}</td>
</tr>
{{/each}}
</tbody>

template rendering is not working properly in ember js

I am very new to Ember js. when i route one template to another it working properly.but the problem is when i was render same template it won't work.
My code is follows:
index.html:Manager template in index.html
<script type="text/x-handlebars" data-template-name="manager">
{{#each model.manager}}
<div class="pure-g-r content-ribbon">
<div class="pure-u-1-3">
<div class="img-viewer-profile">
<img {{bindAttr src="image"}}>
</div>
</div>
<div class="pure-u-2-3">
<div class="l-box">
<h4 class="content-subhead">{{name}}</h4>
<table class="pure-table">
<tbody>
<tr class="pure-table-odd">
<td>Id</td>
<td><b>ATL-{{id}}</b></td>
</tr>
<tr class="pure-table-odd">
<td>Team</td>
<td><b>{{team}}</b></td>
</tr>
<tr>
<td>Division</td>
<td><b>{{division}}</b></br>
</tr>
<tr class="pure-table-odd">
<td>Manager</td>
<td>
<b>
<a href="#" {{action "managerinfo" manager_id}}>
{{manager_name}}
</a>
</b>
</td>
</tr>
{{/each}}
<tr>
<td>Reportees</td>
<td>
{{#each model.results}}
<br><b>
<a href="#" {{action "profileinfo" id}}>
{{reportees}}
</a>
</b></br>
{{/each}}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
{{outlet}}
</script>
app.js:
=========
App.ManagerController = Ember.ObjectController.extend({
manager_id: '',
id: '',
actions:{
managerinfo: function(manager_id) {
// the manager id of selected manager field
var manager_id = manager_id;
alert("profile");
alert(manager_id);
managerdata = $.ajax({
dataType: "json",
url: "/manager?manager_id=" + manager_id,
async: false}).responseJSON
managerdata.manger_id = manager_id;
console.log(managerdata);
this.transitionToRoute('manager', managerdata);
}
)}
Now my problem is when render the new manager data to manager it wont be displayed.
After refresh only it shows the data.
what mistake i was done in this code , i dont understand.so please provide me solution.
i added my complete code here with proper tags order.
As per your comment, the way you are doing is not suggested. You can pass manager_id in the route url. I will give you very basic skeleton which you can make further changes. Do remember, if you want to set model data from ajax, use model hook in the route
First Router
App.Router.map(function() {
this.resource("managers", function(){
this.route("all");
this.route("manager", { path: "/:manager_id" });
});
});
So here with #/manager/all displays all managers list
#/manager/:manager_id displays manager with id manager_id
Next ManagerAll route
App.ManagersAllRoute = Ember.Route.extend({
model: function() {
//do ajax and return managers data which sets as model for this route
}
});
sameway
App.ManagersManagerRoute = Ember.Route.extend({
model: function(params) {
//do ajax and return managers data which sets as model for this route
//here params will have the manager_id passed through url
//as it is ajax, create a promise
return new Ember.RSVP.Promise(function(resolve, reject) {
Ember.$.ajax({
dataType: "json",
url: "/manager?manager_id=" + params.manager_id,
async: false}).then(function(data){
resolve(data);
})
});
}
});
Next is template for managers
{{#each model.manager}}
{{#link-to 'managers.manager' manager_id}}{{{manager_name}}{{/link-to}}
{{/each}}
Now a template for manager
{{manager_id}}
{{manager_name}} blah blah blah
You didn't close the each tag properly.
<script type="text/x-handlebars" data-template-name="manager">
{{#each model.manager}}
<a href="#" {{action "managerinfo" manager_id}}>
{{manager_name}}
</a>
{{/each}}
</script>
Also you haven't closed the ManagerController correctly in the given above. Double check that.
App.ManagerController = Ember.ObjectController.extend({
manager_id: '',
id: '',
actions:{
managerinfo: function(manager_id) {
// the manager id of selected manager field
var self=this;
var manager_id = manager_id;
alert("profile");
alert(manager_id);
managerdata = $.ajax({
dataType: "json",
url: "/manager?manager_id=" + self.manager_id,
async: false}).responseJSON.then(function(managerdata) {
managerdata.manger_id = self.manager_id;
console.log(managerdata);
this.transitionToRoute('manager', managerdata);
})
}
)}

Action handlers implemented directly on controllers are deprecated -how to correct this?

I just upgraded from ember.js RC7 to RC8 and found that a simple template (shown below) would throw a deprecated warning
"Action handlers implemented directly on controllers are deprecated"
{{input class="firstName" type="text" placeholder="first name" value=firstName }}
{{input class="lastName" type="text" placeholder="last name" value=lastName }}
<button class="submit" {{action addPerson}}>Add</button>
<br />
<table>
{{#each person in controller}}
<tr>
<td class="name">{{person.fullName}}</td>
<td><button class="delete" {{action deletePerson person}}>Delete</button></td>
</tr>
{{/each}}
</table>
How should I modify the above template to correct this?
It looks like I just needed to give the PR a look that changed this :)
In my controller I just needed to move the addPerson / deletePerson under actions like so
App.PeopleController = Ember.ArrayController.extend({
actions: {
addPerson: function() {
var person = {
firstName: this.get('firstName'),
lastName: this.get('lastName')
};
App.Person.add(person);
},
deletePerson: function(person) {
App.Person.remove(person);
}
}
});
You should define your actions inside the actions hash in the controllers, views and routes to favour consistency.
Refer this https://github.com/emberjs/ember.js/pull/3091
Demo Fiddle
App.ApplicationController = Em.ObjectController.extend({
actions : {
// your actions here
}
});

Dynamic class binding on a nested child view in #each - how?

I had a single view with an each helper similar to this:
<table class="select-sect" cellspacing="0">
{{#each sections}}
<tr {{bindAttr class="highlight:highlight"}} {{action "selectSection" }}>
<td class="key">
{{#each zones}}
<em {{bindAttr style="color"}}> </em>
{{/each}}
</td>
<td class="sect">{{name}}</td>
<td class="price">{{currency lowPrice}} - {{currency highPrice}}</td>
</tr>
{{/each}}
</table>
Binding a dynamic class like this worked very well. If I set section.highlight == true in a controller, the view would update with the appropriate class.
"Calling" code:
zone.section.set('highlight', true);
Because I need to handle some other events on each row, I've migrated the entire table row to a nested view. I'm searching for a way to make the dynamic class work as it used to.
{{#each sections}}
{{#view SYOS.SelectSectionRowView sectionBinding="this" }}
<td class="key">
{{#each section.zones}}
<em {{bindAttr style="color"}}> </em>
{{/each}}
</td>
<td class="sect">{{section.name}}</td>
<td class="price">{{currency section.lowPrice}} - {{currency section.highPrice}}</td>
{{/view}}
{{/each}}
I don't think I can use the same bindAttr solution since it would need to apply to the #view helper. I've also tried classNameBindings & classBinding to no avail. Updating section.highlight no longer triggers this view to apply the dynamic class.
View w/ classNameBindings:
SYOS.SelectSectionRowView = Em.View.extend({
tagName: 'tr',
classNameBindings: ['isHighlighted:highlight'],
isHighlighted: function () {
return this.section.highlight;
} //also tried .property('section')
});
View with classBinding:
{{#view SYOS.SelectSectionRowView sectionBinding="this" classBinding="needsHighlight"}}
in view class:
needsHighlight: function () {
if (this.section.highlight) {
return 'highlight';
}
return '';
} .property('section'),
Neither of these seems to do the trick. Can anyone lend any insight into how to get a scenario like this going?
Thanks much!
try classNameBindings: ['section.highlight:highlight']