Ember.js - Animate Handlebars Change - ember.js

I am using an {{if}} statement in a handlebars template (in Ember.js) and currently have it setup so if foo is true, a form is displayed.
I have a button which toggles the value of foo and hides/shows the form. This is done with an {{action}} attribute.
What I would like to do is animate this change. If possible, how can I do this using the current setup?
Note: I would be fine with fadeIn/fadeOut (jQuery).

Take a look at Liquid Fire (see: https://github.com/ef4/liquid-fire). I personally didn't work with it yet, but the examples look promising. Especially this form example looks similar to what you want: http://ef4.github.io/ember-animation-demo/#/animated-if-demo
Source is on the next slide: http://ef4.github.io/ember-animation-demo/#/animated-if-source

You can do this way:
in the handlebars file:
<script type="text/x-handlebars" data-template-name="newPost">
<p> Template for New Post </p>
<div class="errorMsg">
<p>Error Message</p>
</div>
</script>
in the view you can set a trigger with an action, and hide the div with the message error
App.NewPostView = Ember.View.extend({
showError: function() {
$('.errorMsg').fadeToggle("slow");
},
didInsertElement : function(){
$('.errorMsg').hide();
this.get('controller').on('showError', this, this.showError);
},
willClearRender: function()
{
this.get('controller').off('showError', this, this.showError);
}
});
And finally in the controller, this must extend to Ember.Evented and when you want to show the message error, you must call a this.trigger error.
App.NewPostController = Ember.ObjectController.extend(Ember.Evented,{
actions:{
// This an example the method that verify and show error after validating
addNewPost: function(post){
if(post.get('name') === 'valid'){
//do your business
}else{
//this will show the message error
this.trigger('showError');
}
}
}
})
when you want to hide the message error, you must call this.trigger('showError') again and this hide the message, you can use this with other effects.

Related

Evaluating controller property everytime the template is rendered in Ember

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()
}
});

Ember partial onload

I'm trying to draw a timeline when the timeline route is opened. Currently have and it partially works, i.e. if you refresh the timeline page, but navigating to timeline page will not draw timeline. I was wondering if it is possible to do {{partial onload="drawTimeline}} or something along those lines.
I've also tried making a handlebars helper {{drawTimeline}} and calling that when partial is loaded, but it is getting an undefined value.
EDIT:
kingpin2k's fix worked for me. This is what I did:
HTML:
{{#view Blocks.Timeline}}
<div id="mytimeline"></div>
{{/view}}
JS:
Blocks.Timeline = Em.View.extend({
didInsertElement : function(){
drawVisualization();
}
});
Is drawTimeline a function on the controller of the current route?
If so, create an associated view and hook up to the didInsertElement and run the function there.
App.SomethingView = Em.View.extend({
didInsertElement : function(){
// do it here
}
});

How to trigger an action on a controller from a template

I have this jsbin. My problem is that I am trying to trigger an action:
<a {{action controllers.nodesIndex.destroyAllRecords this}}><i class="icon-remove-circle"></i><a/>
But I get an:
Uncaught Error: Nothing handled the event 'controllers.nodesIndex.destroyAllRecords'
(You can trigger that by pressing the little icon icon-remove-circle on the top-right, and checking the error on the js console)
But my controller is properly set-up:
App.NodesIndexController = Ember.ArrayController.extend({
destroyAllRecords: function () {
console.log('destroyAllRecords called');
},
});
What am I missing here?
Since the controller for the nodes/index template is the App.NodesIndexController, You need to mention it as controllers.nodesIndex.destroyAllRecords, the default target will be App.NodesIndexController, and so you can just say <a {{action destroyAllRecords}}> as #Thomas told.
Also for getting the length of records, just say {{this.length}} instead of {{controllers.nodesIndex.length}}.
I've updated your jsbin,
You'll need to say as 'controllers.controllername.methodname' only if you are referring to some other controller than the controller for the template, and you've to give the controller's name in the needs list,
say, if you want to call a method of your 'profile' route from your 'nodes/index' template,
then
App.NodesIndexController = Ember.ArrayController.extend({
needs: ['profile'],
});
and in your template,
<a {{action controllers.profile.methodname}}>
Hope it helps.
UPDATE: Refer the solution and the bin in the comment

How to put other events (e.g. focusOut) for the onEvent of Textflied in ember.js to trigger action?

I would like to change emberjs's onEvent which is the trigger to perform the associated view action. There seems to be just 2 options for onEvent: the default enter, and keypress. I'd like to know if I can have other options as well, such as focusOut.
Small question
But first, I couldn't even get the non-default option to work:
Myapp.TextField = Ember.TextField.extend({
onEvent: 'keypress'
});
The text field didn't respond to key presses, but continued to respond to enter.
Actual question
How can we let ember.js text field respond to other onEvents to trigger the action specified in the view. This is something I'm expecting:
HBS:
<script type="text/x-handlebars" id="themodel">
{{view Myapp.TextField action="targetAction" valueBinding="myText"}}
</script>
JS view:
Myapp.TextField = Ember.TextField.extend({
// is this possible?
onEvent: 'focusOut'
});
JS controller:
Myapp.ThemodelController = Ember.ArrayController.extend({
targetAction: function(){
var usertext = this.get('myText');
// do stuff with the usertext ...
}
});
A workaround solution for the "Actual question"
This is a work-around as it doesn't modify onEvent, but directly lets focusOut trigger the targetAction:
JS view:
Myapp.TextField = Ember.TextField.extend({
focusOut: function(){
this.get('controller').set('myText', this.get('value')).targetAction();
}
});
But I really don't like this cumbersome implementation, so please let me know if there is a way to utilize onEvent with focusOut. Thanks.
I experienced something similar to your "small problem", only instead of the text field only responding to enter, it would respond to neither keypresses nor enter.
The solution lies within mavilein's answer to this question - the word "keypress" must be in camelCase, i.e "keyPress". This applies whether it is used as a property name when extending the Ember.TextField class, as you had originally attempted, or as an attribute on the actual view element as Mike had suggested. I tried it both ways. Hope this helps.
But first, I couldn't even get the non-default option to work
Strange. There is a test for exactly this behavior. Suggest having a look and see what's different in your use case.
How can we let ember.js text field respond to other onEvents to trigger the action specified in the view.
Following the same pattern used in Ember.TextField's insertNewLine fx
Myapp.TextField = Ember.TextField.extend({
onEvent: 'focusOut',
focusOut: function() {
sendAction('focusOut', this, event);
}
});

toastr and ember.js

Is the popup library toastr not going to work with Ember because of direct dom manipulation that ember doesn't like?
Are there any other libraries like this one that work nicely with ember?
Edit
Even through the working example posted below I could not get this to work locally. I finally used Pine Notify which worked straight away.
This works fine in Ember, you just have to handle the event in the right place. The "right place" depends on your implementation. If you want this to be fired from a button within your view, you'll need to use the {{action}} helper passing the action name. Example:
<script type="text/x-handlebars" >
<button class="btn btn-info" {{action showInfo}}>Info</button>
</script>
In the template above, I'm saying that the button should fire the showInfo event, so the Controller responsible for this view should have a function with the same name:
App.ApplicationController = Em.ArrayController.extend({
showInfo: function() {
toastr.info('This is some sample information');
}
});
You can also have the view handle the event; the code below defines a click event, so if you click anywhere in the view, it would run your function:
App.OtherView = Em.View.extend({
click: function(e) {
toastr.error('This is some sample error');
}
});
and in your Handlebars template, you don't have do tell the action since you are already saying in the view class that you want to handle the click event for that view, so you can simple render the view and style it:
{{#view App.OtherView class="btn btn-danger"}}
Error
{{/view}}
Here's a sample in JSFiddle: http://jsfiddle.net/schawaska/YZwDh/
I recommend that you read the Ember Guide about the {{action}} helper