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

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']

Related

How to use set new value to an array object for Emberjs view?

How to use set new value to an array object for Emberjs view?
So I have a table of my data; then when I click edit button I want to change the class of the parent <tr> of that button.
So I have this inside my view.
{{#each model as |lineItem index|}}
<tr class="{{ tableRowIndex[index] }}">
<td>
<ul class="dropdown-menu pull-right">
<li>
<a href="#"
{{ action 'editLineItem' this index }} >
Edit
</a>
</li>
</ul>
</td>
</tr>
{{/each}}
This is my controller
tableRowIndex: computed(function(){
let array = [];
this.get('model').forEach(function(){
array.push("");
});
return array;
}),
actions: {
editLineItem(button,index) {
console.log(this.get('tableRowIndex'));
this.set('tableRowIndex[index]','editing-row');
console.log(this.get('tableRowIndex'));
},
}
But it didn't work out so
console.log(this.get('tableRowIndex'));
Output the same result before and after I ran
this.set('tableRowIndex[index]','editing-row');
So how can I make this things work out?
If you wish to set computed property then consider defining it with get and set function.( refer ).
In your case,you just introduce tableRowIndex and initialize it based on model property in setupController hook of route
setupController(controller,model){
this._super(...arguments);
let array = [];
this.get('model').forEach(function(){
array.push("");
});
controller.set('tableRowIndex',array);
}
and in controller.js,
actions: {
editLineItem(button,index) {
console.log(this.get('tableRowIndex'));
this.get('tableRowIndex').objectAt(index,'editing-row')
console.log(this.get('tableRowIndex'));
},
}

EmberJS view is not updating when updating an object in an array

I have a handlebars template where i have a table.
<script type="text/x-handlebars" data-template-name="customers">
<table>
<tbody>
{{#each nomday in allnominationdays}}
<tr class="nomdays" {{action "saveNomDay" nomday on="focusOut"}}>
<td>{{nomday.confirmedVolume}}</td>
<td>{{nomday.variance}}</td>
</tr>
{{/each}}
</tbody>
</table>
</script>
In my controller i have a function which i call from the action saveNomDay defined on the tr.
update: function()
{
console.log('Not Working');
allnominationdays = this.get('allnominationdays');
//this.set('allnominationdays',null);
allnominationdays.objectAt(0).variance = 75;
this.set('allnominationdays',allnominationdays);
},
But my view is not changing when i change the value of the object array. If i set the object array to null the template updates and shows no table. I am not sure what is breaking the binding for the view to update?
the code block updates the view when in a controller function but not when called on a action. But inside the action setting the array of object to null update the view and removes the entire table. Don't know what is going on. New in EmberJS
THanks,
I am too late but better late than never. This is happening because the view is getting rendered before the update in the value can propogate to the screen. Do something like the following code :
--template
{{#if isVisible}}
<table>
<tbody>
{{#each nomday in allnominationdays}}
<tr class="nomdays" {{action "saveNomDay" nomday on="focusOut"}}>
<td>{{nomday.confirmedVolume}}</td>
<td>{{nomday.variance}}</td>
</tr>
{{/each}}
</tbody>
</table>
{{/if}}
--component / controller
self.set('isVisible',false);
var propgationPromise = new Promise(function(resolve, reject) {
//update Value
console.log("promise started");
resolve();
});
propgationPromise.then(function(){
console.log("promise stopped");
self.set('isVisible', true);
});

Can Ember.Select render a promise for content

I'm trying to render out a list of items and provide select inputs for each item. The options for select come from the store, so would be a promise when passed to the Ember.Select. Is this possible? It doesn't look like the view will rerender if the content changes, so it seems like I might have to do that.
My template (abbreviated)
{{#each fruitBins}}
<tr>
<td>{{id}}</td>
<td> {{view Ember.Select
content=fruitTypes
optionLabelPath="content.name"
optionValuePath="content.id"
prompt="Select a Fruit Type"
}}
</td>
</tr>
{{/each}}
fruit_bins_controller.js:
...
fruitTypes: function () {
return this.store.find('fruitType');
}.property(),
The only thing that appears when the select is rendered is the prompt.
Ember: 1.3.1, Data: 1.0.0.beta4
Turns out I was wrong understanding my issue.
Made the updates as #edpaez suggested, which I think aligns my code with conventions. I added the following to my route:
model: function () {
return Em.RSVP.hash({
content: this.modelFor('<the parent element>'),
fruitTypes: this.store.find('fruitType')
});
},
setupController: function(controller, model) {
controller.setProperties(model);
}
I still had the same problem though and found (forgot) that using the #each changes my context.
The solution was to wrap the #each:
{{#with this as context}}
{{#each fruitBins}}
<tr>
<td>{{id}}</td>
<td> {{view Ember.Select
content=context.fruitTypes
optionLabelPath="content.name"
optionValuePath="content.id"
prompt="Select a Fruit Type"
}}
</td>
</tr>
{{/each}}
{{/with}}

Don't want to use any tag(including the default div tag) in Ember.Collection View

Title may sound stupid, consider the following code
My Handlebars File
<table id="main-table">
<tr>
<td>
<h1>Some Text</h1>
</td>
{{#collection myCollectionView}}
<td>
<table>
<tr><td>{{view.someProperty}}</td></tr>
</table>
</td>
{{/collection}}
</tr>
</table>
My View File
myCollectionView = Ember.CollectionView.extend({
contentBinding: "myController.someArray",
//someArray has say 4 elements
itemViewClass: Ember.View.extend()
})
I want it to render the 4 tables inside the #main-table, it instead renders them outside the #main-table because it encloses my itemViewClass inside the default div tag. I can only change the tagName property but can't set it to nil I guess, any hack for this issue?
The JSFiddle
In response to the first answer
The problem with {{each}} is that, I am using an EditableField as follows:
(just to sound clear, editable field is the one which changes a div to textfield on double click & back to div tag on focus out, simple widget built using ember)
updated Handlebars file
<table id="main-table">
<tr>
<td>
<h1>Some Text</h1>
</td>
{{#collection myCollectionView}}
<td>
<table>
<tr><td>{{view.myEditableField valueBinding="view.content"}}</td></tr>
</table>
</td>
{{/collection}}
</tr>
</table>
updated view file
myCollectionView = Ember.CollectionView.extend({
contentBinding: "myController.someArray",
//someArray has say 4 elements
itemViewClass: Ember.View.extend({
alertFunc: function(){
alert("content did change");
}.observes('content')
})
})
I want an observer to fire whenever the value in one of the editableField is changed, so that I can update my records in database. Can we accomplish this thing using {{each}} helper? also, arrayContentDidChange will only fire if the array length changes
It is possible to do this in a Ember View
App.MyView = Ember.View.extend({
tagName: ''
});
AFAIK, there can't be Ember.View without "real presence" in the DOM, but you can use the {{each}} helper if you don't want to add a view that acts as a container (here a Ember.CollectionView).
Set tagName to null does not work, see Ember.View source code.
Template:
<script type="text/x-handlebars">
<table id="main-table">
<tr>
<td>
<h1>Some Text</h1>
</td>
{{#each App.content}}
<td>
<table><tr><td>{{name}}</td></tr></table>
</td>
{{/each}}
</tr>
</table>
</script>​
Code:
App = Ember.Application.create();
App.content = [{name: "foo"}, {name: "bar"}, {name: "baz"}];
​
See this JSFiddle.

How to use view as a replacement for tr tag

regarding the different posts I read I would have expected that the following code should work:
<tbody>
{{#each NewApp.router.gridController.tableContent}}
{{#view NewApp.TableRow rowBinding="this"}}
<td style="width: 100px">{{row.item_no}}</td>
<td align="right" style="width: 100px">{{row.price}}</td>
<td>{{row.name}}</td>
{{/view}}
{{/each}}
</tbody>
But I get only empty table rows. If I use tr everything works as expected.
The TableRow is defined as:
NewApp.TableRow = Ember.View.extend({
tagName: "tr",
row: null,
willInsertElement: function() {
console.dir(this.get("row"));
}
});
BTW: console.dir shows the correct data.
Regards
Roger
You can take a look at http://docs.emberjs.com/#doc=Ember.CollectionView&src=false, it can simplify your code.
For your example, use {{view.row.XXX}} in the template, it should do the job