How to add a carousel to an ember site - ember.js

I would like to add a carousel, preferably caroufredsel http://caroufredsel.dev7studios.com/, to a few templates/routes on an ember site. I was wondering what the best way to do that would be?
All that is needed to fire the items that you want to slide is the following jQuery function:
$(document).ready(function() {
$("#foo1").carouFredSel();
});
Where do you think the best place in the app to put this is?

The best place it to create a custom View for the template that will have the carousel. Then use the didInsertElement hook to initialize the widget once the markup for the carousel once it is in the document. You can also use the willDestroyElement hook to tear down the carousel before the markup is removed from the document.
So, say that you have a /carousel route, and then you have this as your 'carousel' template.
<div id="foo1">
<!-- Other carousel markup goes here-->
</div>
Then you'd create a View like this.
App.CarouselView = Ember.View.extend({
didInsertElement : function(){
$("#foo1").carousel();
},
willDestroyElement : function(){
$("#foo1").trigger("destroy");
}
});

Related

Ember re render component

I have a component with a jquery menu that transforms the DOM. I need to re render the component for initiate the structure again. The jquery menu doesn't work dinamically, so I need to re render the component.
//Parent Component hbs
<div id="container">
{{menu-jquery model=model}}
</div>
//Parent Component js
export default Ember.Component.extend({
refreshMenuData(){
callToServer()// ajax call
updateModel()// generate model from ajax response
-> //how to delete and create menu component? or re render menu component?
}
}
Thanks
A component has a function called rerenderthat you can call to force a rerender of the component. Although, I might recommend a better approach. Upon resolution of the promise that fetches your server data, manually destroy the jquery plugin and then reinit said plugin.
I found a workaround putting the component inside a conditional block. I set loading in false before the server call and true after data parsing.
{{#if loading}}
// show loading message
{{else}}
{{menu-jquery model=model}}
{{/if}}
This force the menu component to re render.
Your question is not quite clear. I am assuming that, you will be using jquery ajax for server calls inside the component. In Ember.Component, you have to use .on("didInsertElement") which works similarly as that of jQuery(document).ready(). So your component will look something like this
export default Ember.Component.extend({
_onReady: function() {
refreshMenuData();
//whatever jquery code you want to execute here
}.on('didInsertElement')
})
If you can provide your example in Ember Twiddle or JSBin, I can help you better.

EmberJS - Rendering separate route as a modal into a specific outlet

In my EmberJS applications I have two separates routes as follows,
Route A - "main/books/add"
Route B - "main/authors/add"
I have an "Add Authors" button In Route A template and when a user presses that button I want to load and render Route B in a modal to add new authors.
I know its possible to achieve somewhat smiler to this by using the route's render method to render the Route B template and respective controller.
But in that case, the "model" hook of Route B in "main/authors/add.js" file does not get invoked.
It would be really nice if someone can suggest me a method to render a separate route into a modal.
EDIT - Although this is entirely valid (the premise of rendering into using named outlets, views are now deprecated in Ember 1.1. The same can be achieved by using a Component
Yup, you can do this:
What you'd want to do is create a modal in a template and assign a named outlet into it (or create a view that is a modal with an outlet):
in modal.hbs:
<div class='modal'>
{{outlet "modalContent"}}
</div>
Then I would override your base button like so:
App.BasicButton = Em.View.extend({
context: null,
template: Em.Handlebars.compile('<button>Click Me!</button>');
click: function(evt) {
this.get('controller').send('reroute', this.get('context'));
}
});
And in your template set up your button to trigger your modal:
in trigger.hbs
<!-- content and buttons for doing stuff -->
{{View App.BasicButton context='modalContent'}}
Finally, you want to create a method in your route which handles rendering specific content into your outlet:
App.TriggerRoute = Em.Route.extend({
actions: {
reroute: function(route) {
this.render(route, {into: 'modal', outlet: route});
}
}
});
So in essence, you're rendering the template (called "modalContent") into a specific outlet (called "modalContent"), housed within the template/view (called "modal")
You would also want to write some logic to trigger the modal to open on element insertion. To do that, I would use the didInsertElement action in the modal view:
App.ModalView = Em.View.extend({
didInsertElement: function() {
this.$.css("display", "block");
//whatever other properties you need to set to get the modal to pop up
}
});

Emberjs outlet inside a bootstrap popover

I'm using bootstrap popover in my app and I need to render an outlet inside it.
I have this nested route :
this.resource('pages', function(){
this.resource('page', { path: ':id' }, function(){
this.resource('edit', function(){
this.resource('images', function(){
this.resource('image', { path: ':image_id'}, function(){
this.route('edit');
})
});
});
});
});
When the user is here => /pages/1/edit/ when he click on an image it route to /images but render the {{outlet}} inside the popover like this :
<div class="popover-content hide">
{{outlet}}
</div>
This is my popover initialisation :
$img.popover({
html: true,
content: function() {
return $('.popover-content').html(); //need to have the outlet here
}
});
So far, it render correctly my outlet, but inside the images template, I have some button that modify the DOM and it doesn't update the html. Unless if I close and open the popover again I can see the modification.
Is it possible to render the outlet directly inside the code ? or is it possible to have my popover being updated ?
Thanks for the help.
See these links for an alternative approach to putting Ember stuff in Bootstrap popovers:
Bootstrap Popovers with ember.js template
https://cowbell-labs.com/2013-10-20-using-twitter-bootstrap-js-widgets-with-ember.html
Ember and Handlebars don't like this because it's basically copying the html content of a div and plopping it into another. But that html alone isn't everything that's needed. Ember is magic and there's lots of stuff happening in the background.
Your hidden div is real ember stuff, so let's try not to mess with it by calling .html() on it. My idea is to literally move the DOM itself instead.
first, modify your popover function call to always create this placeholder div:
content: '<div id="placeholder"></div>',
next, detach the content div from the dom in the didInsertElement of the view:
// get the popover content div and remove it from the dom, to be added back later
var content = Ember.$('.popover-content').detach();
// find the element that opens your popover...
var btn = Ember.$('#btn-popup-trigger').get(0);
// ... and whenever the popover is opened by this element being clicked, find the placeholder div and insert the content element
// (this could be improved. we really just want to know when the popover is opened, not when the button is clicked.)
btn.addEventListener("click", function() {
content.appendTo("#placeholder");
});
since the content div is immediately detached when didInsertElement is called, you can remove the "hide" css class from the content div.
edit: i tried this on my own project and it broke two-way binding. the controller updated my handlebars elements, but any two-way bound {{input}} helpers did not update the controller/model. i ended up using a single-item dropdown menu, and used this to prevent the menu from closing too quickly:
Twitter Bootstrap - Avoid dropdown menu close on click inside

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

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