Integrating external JS libraries in Ember - ember.js

I have a simple application that uses jqplot to graph data. This application has a single route attached to an ArrayController. I display the items to be graphed on the left side using the {{#each}} helper; I also display a 'graph' button up top. The user can select one or more entries from the list and hit the graph button. The button is attached to an action that calls jqplot to graph the selected data on the right side. Functionally, this works fine, but feels like a hack. Does anyone have an opinion on how this can be re-structured to perform similar function the 'Ember way'?
This app only has one model, so doesn't seem like I would need a second route. I do need to somehow handle re-graphing if the user resizes the window. If I weren't using Ember, I would handle window resizing like this:
$(window).resize(function(){
plot1.replot ({resetAxes: true});
});
where 'plot1' is the return value from the original call to jqplot.
How do I do this in Ember?
I'm using Ember 1.4 with EmberData beta 7.

You can put custom JS code in the didInsertElement() hook of your view, which will be executed after the view is rendered.
There's a corresponding willDestroyElement() hook for your teardown code.

Related

ember.js beginner advice required

I am attempting to learn ember.js to produce a simple-ish web application. I have read around the subject and completed the basic tutorial on emberjs.com . So far, I have managed to create the beginnings of an API using PHP and I have been able to retrieve that data into my fledgling application. So far so good.
As a starter, I wish to retrieve a list of users from the server and populate a select with these values. The select is to sit on the menu bar and the selection from this drives the rest of the data for the application. I have placed the model in models/users.js. The application menu I have defined in templates/application.hbs (not sure if this is considered correct or not).
I am unable to get the users data for the select retrieved from the server unless I visit the users route that I have also setup. How can I ensure that the users data is populated at application initialisation? How would I apply/filter the rest of the application data upon selection from this component - would I need to set a global variable or something?
Additionally, I am using materializecss, which requires $('select').material_select(); to be run in order to render the select input. I have this as:
$( document ).ready(function(){
$('select').material_select();
});
in templates/route.js and works fine on initial page load, but upon navigation to another area and back again, the select is not rendered, and from what I have read, I need to call material_select() again, but I can't for the life of me work out where this call should go.
If anyone is willing to take the time to help me better understand things, I will be very grateful.
Cheers
Tim
Preloading Clarification
I wish to have a select box on the main menu bar (menu-bar component). The user will use this to select a user. All content in the app will be filtered to the currently selected user. I currently have an API endpoint (/users.php) which returns the required data, but I am only able to get my application to call this when I visit the users route, which obviously I won't be doing when the app loads initially. So I am thinking I need to preload the data somehow, unless there is a better way that I am not aware of?
Create a component for menu and put the component in application.hbs
And in component put the materialize stuff like this : (notice to the place)
//components/menu-bar.js
didInsertElement(){
this._super(...arguments);
Ember.$( document ).ready(function(){
Ember.$('select').material_select();
});
}
And
//templates/application.hbs
{{menu-bar}}
{{outlet}}
UPDATE
Create a service holding current user selection and use it in other places that you want be changed by changing the user selection.
These codes is just for showing that the solution for what you want (changing the other parts of app based on changing the selected user in menu) is services.
//services/current-selection.js
...
selectedUser: null,
...
and
//components/menu-bar.js
currentSelection: Ember.inject.service(),
actions: {
selectUser(user){
this.set('currentSelection.selectedUser', user);
}
}
and in another place you want to be notified when selection changed :
//components/user-info.js
currentSelection: Ember.inject.service(),
and corresponding template
//templates/components/user-info.hbs
{{#if currentSelection.selectedUser}}
<span>Current Username: <strong>{{currentSelection.selectedUser}}</strong></span>
{{/if}}
Update For pre-loading users
Actually it's not pre-loading
In menu-bar component you load a select box and populate it by calling a service to backend. If you put this component in application.hbs you could ensure what you want is satisfied.
//components/menu-bar.js
store: Ember.inject.store(),
users: Ember.computed(function(){
return this.get('store').findAll('user');
}),
OR
In application route model hook you fetch those users and pass to component like {{menu-bar users=model}}
And for these two options you can use users in menu-bar template.
But pay attention to that if the users count is a lot, this is very bad for performance or UX. If your users are a lot it's better to use from a autocomplete component

Make Ember router transition to route from a click event

I got a Leaflet map rendered as a view with controller in application template like {{view "map" locations }}. locations is an array of location models.
In index route the locations data is loaded and set on application controller to be passed on to the map view. This happens that way because other routes can set another content for locations and so change the markers on the map.
In the map view the Leaflet map is set up and the markers are created from locations. I want to be each marker to be clickable, so the app transitions to the route where the “clicked” location is described in detail. Therefor I have to bind a click event handler right after creation when I have the location model at hand like
mapMarker.on('click', function(ev) {
// Do transition to 'location' with model location
});
I’d love to keep the routing stuff in the router/routes. In a template I’d use a link-to helper, but how to a transition from a click event defined within a view? I tried to use sendAction but it seems this doesn’t work here because of the view being rendered in its on scope so the action doesn’t bubble up to application route. Any ideas?
For the click event to bubble up to the routes you have to send it to the current controller.
this.get('controller').send('someEvent')
Doing just send() makes the action bubble up only to parent views.
Now, if you were to use the action helper in your template, in that case it goes directly to the controller. And if the controller doesn't implement the action, it will bubble up to the route.
See http://emberjs.com/guides/templates/actions/#toc_action-bubbling

Rerender view after change route's dynamic segment

I have a Route with dynamic segment :id. When I change only the dynamic segement part manually in browser url input field, then goes a transition, and all model hooks are called as expected.
The problem is: none of the views are rerendered. I guess it is because only model changed - not the UI. But I have some UI logic in views' didInsertElement handler - reinitialize UI plugins and so on.
How to force ember to rerender view after dynamic segment change?
I agree with the josh's comment. if you are rerendering views with the change of dynamic segment means your code is not written properly. But still if you want to go like that i am gonna give is a part of code.
In your route:
model: function(params){
model.set('id', params.id);
}
In your view which needs to be rerendered:
_modelIdChange: function(){
this.rerender();
}.observes('controller.model.id')
But i don't suggest this. I would rather prefer proper bindings. But i did use rerendering in some cases which mostly when you end up using jquery plugins.

Ember View loses content

I am working on a bit of code to show a D3 chart using Ember fixture data as the source for the data. The charts show up just fine on the first load of the page but if I move to a different route & then return to the first route (the one with the working chart) the chart simply disappears. So I guess my question is, how do I get the chart to appear every time the route is visited? Here is what my Route and View code looks like, will add more code if requested.
Updated with JS Bin: http://jsbin.com/ihapaz/2/edit
The route may not be getting any data when you return back to it. When using linkTo the model hooks are not fired. The setupController is called directly with the model that you pass to linkTo. However if the route depends on the model hook having fired to load it data then the view would be empty as it wouldn't have any data to render.
That's the only thing that comes to mind from the above code. Try posting a jsbin if this doesn't work.
Edit: Post jsbin
After looking at your jsbin I realized my earlier answer was incorrect. In general it is true that linkTo skips the model hook, but only if dynamic segments are present. Your route has no dynamic segments. Hence the model hook will always be called, so the view/chart is getting data correctly.
The error is in your implementation of render. The purpose of the render method is to push strings of html onto the DOM. This isn't the appropriate place for custom DOM insertion. For that you need to put things on the didInsertElement method.
I made these changes, renaming render to didInsertElement and the corresponding updateChart. Here's the updated jsbin.

What is the ember way to add popovers to views?

I'm working on a events board app. Events are displayed in columns at the height matching the start time and pack into the space if there is more then one overlapping. Each event is a view and I want to have a div next to the view that shows and hides on hover.
I know how to bind to mouseEnter and mouseLeave to show and hide part of the template but I want to show something adjacent to my view/template not within it.
I've already got some computed properties on the view to place the event with the correct height and width so I don't want to add the popover inside the view.
Here is something to mess with http://jsbin.com/osoner/1/edit
Seems like something simple but I want to make sure I'm doing things the Ember way.
After messing a little with your provided jsbin, here the results.
Basically what I've done was adding a new popup css declaration wich do position the popup so that it appears outside the parent view, and also moved the {{#if...}} helper into the originating view.
If you want to go more fancy, checkout this jsfiddle wich uses the twitter boostrap popover.
Hope it helps.