Evaluating controller property everytime the template is rendered in Ember - ember.js

I have a template called sample and I am changing the property show in the controller based on a button press. Now I want the controller to reset the property every time the template is rendered. Currently even if I go to 'next' template and come back, the property show remains true if the button on sample was pressed. I want to change this behaviour and the property show should be false by default. I know I can do this by defining a view and using the didInsertElement hook but is that the only way to do this?? Ember.js website says that Views in Ember.js are typically only created for the following reasons:
When you need sophisticated handling of user events
When you want to create a re-usable component
and I am doing none of the above. Here is some sample code:
<script type="text/x-handlebars" data-template-name="sample">
{{#if show}}
Showing stuff
{{/if}}
<button {{action changeShow}}>Change</button>
{{#link-to 'next'}} Next {{/link-to}}
</script>
<script type="text/x-handlebars" data-template-name="next">
Hello
{{#link-to 'sample'}}Back{{/link-to}}
</script>
App.SampleController=Ember.Controllers.Extend{(
show:false,
actions:{
changeShow:function(){
this.controllerFor('sample').set('show',true);
}
}
)};

you can use didTransition action which will trigger automatically once the transition happened. didTransition action
App.SampleController=Ember.Controllers.Extend{(
show:false,
actions:{
didTransition:function(){
this.controllerFor('sample').set('show',false);
},
changeShow:function(){
this.controllerFor('sample').set('show',true);
}
}
)};

You can use the renderTemplate hook for the route you're doing this in, and change the controller variable in there.
http://emberjs.com/api/classes/Ember.Route.html#method_renderTemplate
I'd do something like this:
App.PostsRoute = Ember.Route.extend({
renderTemplate: function(controller, model) {
var favController = this.controllerFor('favoritePost');
favController.set("toggle", false)
this._super()
}
});

Related

observer fire action to early. before action is initialize observes fired the action

Template
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
<ul>
{{input type="text" value=model.name}}
</ul>
<p {{action 'test'}}>test</p>
</script>
ember code
App = Ember.Application.create();
App.Router.map(function () {
// put your routes here
});
App.IndexRoute = Ember.Route.extend({
model: function () {
return Ember.Object.create({name:'dilip'});
},
actions:{
test:function(){
alert('route test');
console.log('test')
}
}
});
App.IndexController = Ember.Controller.extend({
handleChange:function()
{
console.log('handle')
this.send('test')
}.observes('model.name')
})
action 'test' is already defined in route but its showing below error.This error comes only when i am using observes.
Error while loading route: Error: Nothing handled the action 'test'.
The observer does fires before the route is ready to handle the action. This kinda, sorta makes sense because the controller is "built" as part of the route. I've solved this by setting a property within the routes setupController hook to let the controller know that it's ready for action!
// Route
setupController: function(controller, model) {
this._super(controller, model);
controller.set('routeIsReadyForAction', true);
}
// Controller
routeIsReadyForAction: false,
someObserver: function() {
if (!this.get('routeIsReadyForAction')) {
return;
}
this.send('someRouteAction');
}.observes('someProperty'),
You need to handle the action in the controller, not in the route. Check out this jsbin: http://emberjs.jsbin.com/yubowi/edit?html,js,output
You should define your action within controller.
this.send('test') Looks for actions in this extended class (in this case controller). If u make this.sendAction('test') It goes out and looks for actions but these have to be predefined like so `actionName="actionName". This is mostly used when you have a component that needs to interact with a controller
{{my-component actionName="actionName"}} < sendAction now looks for controllers action

Dynamic value in application template

I tried to implement user name displaying after log in. It displays in top menu. But top menu is getting displayed before log in, so it user name is getting cached.
I tried many approaches, and using volatile() is seems the best option, but it doesn't work. In this simple example currentTime calculates only once:
<script type="text/x-handlebars" data-template-name="application">
{{currentTime}}
</script>
App.ApplicationController = Ember.Controller.extend({
currentTime: function() {
console.log('computing value');
var time = new Date();
return time;
}.property().volatile()
});
Ember version 1.3
P.S. I prepared the gist to illustrate this issue: http://jsbin.com/OPUSoTaF/1
Actually, I can't find ANY way do display dynamic value in Ember's application template. Tried to display value from another controller using {{render}} helper, value still gets cached.
It seems that I just need to update value on ApplicationController from some other controller, and to do it in a proper way. Like this:
App.LoginController = Ember.Controller.extend({
needs: 'application',
setTime: function() {
this.get('controllers.application').set('currentTime', new Date());
}
});
The application to illustrate: http://jsbin.com/OPUSoTaF/4/edit
You can change ember properties and thus views using Handlebars {{action 'actionName'}} helper. You can add action helper to almost any UI element in your handlebars template an it is usually triggered on click. When triggered it calls actionName method on the controller.
Example:
Handlebars template:
<script type="text/x-handlebars" data-template-name="application">
<button {{action 'login'}}>Login</button>
{{loginTime}}
</script>
Controller:
App.ApplicationController = Ember.Controller.extend({
loginTime: 'User not logged in yet',
actions: {
login: function() {
// ... Do some login stuff ...
this.set('loginTime', new Date());
}
}
});
Working jsbin example is here: http://jsbin.com/udUyOXaL/1/edit

Emberjs 1.0.0-RC3: Is there a better way to set model property for #render

The code works and here is the jsfiddle for the code. But, I don't like the approach I am using to get {[render}} to work. For now to be able to use {{render events}} in application-template, I need to set it in the application-route using setupController and then calling controllerFor('events'), otherwise it won't work. But I have already defined an EventsRoute with a model hook for setting up the controller content and will prefer for {{render helper}} to use the model set in the EventsRoute.
I was wondering if there is a better or more idiomatic way to do this in ember besides my present approach of going to ApplicationRoute.
Relevant code*
App.Router.map(function(){
this.resource('events');
});
The {{render 'events'}} in application template only works when i set the model via application route.
App.ApplicationRoute = Ember.Route.extend({
setupController: function(){
this.controllerFor('events').set('model', App.Event.find());
}
});
I would prefer to {{render 'events'}} to work with the content set here but it doesn't. But I am keeping for now to use in places where it might make sense to use {{#linkTo}}.
App.EventsRoute = Ember.Route.extend({
model: function(){
return App.Event.find();
},
setupController: function(controller, model){
controller.set('content', model);
}
});
The templates
<script type="text/x-handlebars" data-template-name="application">
{{render 'events'}}
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="events">
<button {{action 'yEmpty'}}> log event content is empty</button>
{{#each controller}}
<h3>{{title}}</h3>
<p>{{start}} - {{end}}</p>
{{/each}}
{{outlet}}
</script>
I'm unsure of what you're trying to do. Do you want events and appointments to be rendered at the same time on one page? If yes, then, I think, you need to use render (much like you do in your jsfiddle). If not, you could remove {{render 'events'}} and setupController hook on ApplicationRoute and redirect to events route.
I found this issue with Fixture Adapter and looks like it doesn't work with hasMany (therefore jsfiddle example won't work) but I assume you are using RESTAdapter.
UPDATE:
Another place to set the model is in init hook like so:
App.EventsController = Ember.ArrayController.extend({
init: function () {
this.set('model', App.Event.find());
}
});
Personally, I would left the code in setupController hook.

Ember JS - view insertion event

I have the following Handlebars template which contains some views that are being output in an #each.
<script type="text/x-handlebars" data-template-name="thread">
{{#view My.ContainerView}}
{{#each message in messages}}
{{view My.MessageView contentBinding="message"}}
{{/each}}
{{/view}}
</script>
I am using the didInsertElement event to catch the insertion of the parent view.
I know there is didInsertElement fired on insertion of each My.MessageView but what I was wondering was if there was an event fired when all of the My.MessageViews were inserted? Meaning the #each is finished. Maybe there is a similar event for a view being fully rendered?
// Ember Noobie
I've run into a similar scenario, in regards to where to fire a jquery event after child views have rendered. With some help from this forum, I ended up with something like this:
The view below is rendered once for each item that I ajax in (for a bootstrap accordion).
App.AccItemView = Em.View.extend
classNames: ['accordion-group']
templateName: 'acc_item'
didInsertElement: ->
Ember.run.next this, ->
#.$('.collapse').collapse({parent:"#accordion2"})
There's also an afterRender hook, which I'm still experimenting with myself.
didInsertElement: ->
Ember.run.scheduleOnce 'afterRender', this, () ->
#.$('.collapse').collapse({ parent:'#accordion2'})
A fiddle is here, if it is of any use.
http://jsfiddle.net/nrionfx/s59fA/16/

using emberjs new-router-V3 and #with helper to access events defined in a different route

I have this working jsfiddle. The EmBlog.PostsEditRoute has a destroyPost event which I want to call with an action helper in the 'post/show.hbs' which is the template for the EmBlog.PostsShowRoute.
I am using #with helper to change scope in the template as suggested here. It doesn't destroy the object and throws no error.
<script type="text/x-handlebars" data-template-name="posts/show">
{{#with EmBlog.PostsEditController}}
<a href='#' {{action destroyPost this}}> Destroy</a>
{{/with}}
</script>
EmBlog.PostsShowRoute = Ember.Route.extend({
});
EmBlog.PostsEditRoute = Ember.Route.extend({
events: {
destroyPost: function(context) {
var post = context.get('content');
post.deleteRecord();
post.get('store').commit();
this.transitionTo('posts');
}
}
});
I think this is basically because you have to define your event handler in the EmBlog.PostsShowRoute or in the PostsRoute if you want it to be accessible in an other PostsXXX view. see http://emberjs.com/guides/templates/actions/ for details.
(the use of the #with helper here seems wrong here BTW, as your reference is about something quite old). I would simply do
<script type="text/x-handlebars" data-template-name="posts/show">
<a {{action destroyPost content}}> Destroy</a>
</script>
Here is the modified fiddle: http://jsfiddle.net/Qn3ry/4/
Note that when you try to destroy a post which is in the fixtures, it reappears when you transition to posts/index. This is simply because the post is not destroyed in the fixtures, and when entering to the PostIndexRoute, App.Post.find() will reload it again.