Loading a 3rd party embed widget within an Ember.View - ember.js

I'm loading the RebelMouse embed widget into an Ember.View, like so:
App.RebelMouseView = Em.View.extend({
didInsertElement: function() {
var widgetEmbedCode = '<script type="text/javascript" class="rebelmouse-embed-script" src="https://www.rebelmouse.com/static/js-build/embed/embed.js?site=W3portals&height=900&flexible=1"></script>';
this.$().append(widgetEmbedCode);
}
});
But I'm hoping there's a better way to do so.
One undesired side-effect is that everytime I initialize that view it reloads the entire widget with a 1 second delay. Thanks.

Ok, good idea on showing/hiding, see http://jsfiddle.net/9EC8F/ for how to do it. Basically, the trick is to keep the view outside any outlet that will be torn up when the route changes. Then, put this in your route:
activate: function() {
$(".rebel-mouse-view").show();
},
deactivate: function () {
$(".rebel-mouse-view").hide();
}
and this in your view:
classNames: ['rebel-mouse-view'],

Related

Emberjs - Pass an object from the view to controller

I am using a radialProgress as a jQuery plugins (homemade), and I need to implement it for ember but I have some issue to do that.
Quick explanation for the plugins :
var chart = $(yourElement).pieChart(options); // initialise the object to an element
chart.setCompleteProgress( complete, false ); // set how many item you have to complete the task
chart.incrementProgress(); // increment + 1 every time you call it
It's a very simple progress pie.
In my case my task are located inside my controller, but the chart as to select a dom element so I need to initialise it inside my view.
My task in the controller are called from the router from the setupController to reload the model over time.
Here is a small sample of what I would like to do :
App.ApplicationRoute = Ember.Route.extend({
setupController: function(controller) {
var promise = controller.getModel();
this._super(controller, promise);
}
})
App.ApplicationController = Ember.ArrayController.extend({
getModel: function() {
// chart.setcompleteProgress();
// A lot of code are here to get some data
// chart.incrementProgress();
return newModel;
}
})
App.ApplicationView = Ember.View.extend({
didInsertElement: function() {
var chart = $(element).pieChart(opts);
}
})
I don't know how to pass the chart object from the view to the controller to be able to have access to my plugin function.
Che chart won't be inserted into the DOM until the didInsertElement therefore you can't attempt to manipulate it in the route during setupController etc. I'd suggest creating a method in the controller setupChart and calling that on didInsertElement.
App.ApplicationView = Ember.View.extend({
prepPieChart: function() {
var chart = $(element).pieChart(opts);
this.get('controller').setupPieChart(chart);
}.on('didInsertElement')
})
App.ApplicationController = Ember.ArrayController.extend({
setupPieChart: function(chart) {
chart.setcompleteProgress();
// A lot of code are here to get some data
chart.incrementProgress();
}
})
All that being said, maybe it belongs in the view, but I'm not sure of what you're completely doing.

Execute code once after all views have completely rendered in Ember.js

Something like document ready, but after all Ember views rendering
I am doing this right now with an override on ApplicationView didInsertElement, which seems to be working so far:
App.ApplicationView = Em.View.extend({
didInsertElement: function() {
// Do your magic.
}
});
I am wondering if this is the right way for an Ember document ready, or if Ember has a more native support for this simple and very common thing.
You can easily add a "post render" hook by reopening the base View class and adding it into the render queue.
Here's some code to show you how:
Ember.View.reopen({
didInsertElement : function() {
this._super();
Ember.run.scheduleOnce('afterRender', this, this.didRenderElement);
},
didRenderElement : function() {
// Override this in your View's
}
});
The didInsertElement is the right place, but if you want to be completely sure your render queue is completely flushed you could also listen to the afterRender event, something like this:
App.ApplicationView = Ember.View.extend({
didInsertElement: function() {
Ember.run.scheduleOnce('afterRender', this, 'processChildElements');
},
processChildElements: function() {
// do here what you want with the DOM
}
});
Hope it helps.
App.ApplicationView = Ember.View.extend({
afterRender: function () {
Ember.run.next(this, function () {
// This will run one time, after the full initial render.
});
}
});

How can catch event after template is rendered at EmberJS?

I have an application that uses masonry and Ember JS I attempt to search DOM an element by selector, but it retrieves null It seems I do it early than template was rendered. Please, help me resolve it.
#GJK answer is correct, I just want to provide a working example: http://jsbin.com/enijad/3/edit
App.IndexView = Ember.View.extend({
didInsertElement: function() {
var $container = $('#container');
$container.masonry({
columnWidth: 150,
itemSelector: '.item'
});
}
});
The didInsertElement function will be called when the view was inserted into the DOM, so it will be safe to initialize additionally libraries.
Also worth mentioning is that if you need some clearing up after the view was removed from the DOM you would do this in didInsertElement's counterpart hook willDestroyElement.
Example:
App.IndexView = Ember.View.extend({
didInsertElement: function() {
// do initialization here
},
willDestroyElement: function() {
// and here you can remove stuff safely
}
});
Hope it helps.
Create a corresponding View for your Route and Template, and then override the didInsertElement method.

Access data from controller in view in didInsertElement

I am trying to access data from DashboardIndexController in DashboardIndexView
JP.DashboardIndexController = Ember.Controller.extend({
users: []
});
Is it possible to access users in JP.DashboardIndexView in didInsertElement?
didInsertElement : function(){
console.log(this.get("controller.users").objectAt(0));
}
This is my DashboardIndexRoute:
JP.DashboardIndexRoute = Ember.Route.extend({
setupController: function(controller, model) {
controller.set('users', JP.User.find());
}
});
Thank you
EDIT
console.log(this.get("controller.users").objectAt(0));
Returns data only when I go to UsersIndex and then back to DashboardIndex... I think it's something with initialization, but I don't know, how to fix it.
Yes, this is how to access the list of users.
This happens because the DashboardIndexView is inserted into the DOM before the controller.users is populated with data from the server.
So when the view is rendered, controller.users is still empty, and will asynchronously be populated after the ajax request finishes, problem is, didInsertElement already fired.
In order to solve this, you need to access controller.users from another hook. DidInsertElement is the wrong place, because it will fire irrespective of whether JP.User.find() finished loading.
You just need to make sure that it re-fires when JP.User.find() is loaded even if view is already in the DOM. Something like this:
JP.DashboardIndexView = Ember.View.extend({
didInsertElement: function() {
this.usersChanged();
},
usersChanged: function() {
if (!this.$()) { return; } // View not in DOM
console.log(this.get('controller.users'));
}.observes('controller.users.#each')
});

ember - didLoad event in view for waiting for a ember-data model to load

hi i have the following route:
MB3.PlaylistRoute = Ember.Route.extend({
model: function(params) {
return MB3.Playlist.find(params.playlist_id);
}
});
The playlist has a hasMany realtion with tracks. in the playlist view i want do do some logic with an attribute of the first track of the playlist.
so i added this code:
MB3.PlaylistView = Ember.View.extend({
didInsertElement: function() {
console.log(this.get("controller.tracks").objectAt(0).get("title"));
}
});
The problem is title is undefined (i think because it is not yet loaded. the second thing i tried is waiting for the didLoad event:
MB3.PlaylistView = Ember.View.extend({
didInsertElement: function() {
var self=this;
this.get("controller.tracks").on("didLoad", function() {
console.log(self.get("controller.tracks").objectAt(0).get("title"));
});
}
});
but this logges null as well. How do i accomplish that?
Like Adrien said in the comments, it seems you are running into issue 587. That said, I don't think you actually need the "didLoad" callback in this case. Instead, try using a computed property to get the video_id or track title. For example:
MB3.PlaylistView = Ember.View.extend({
firstTrackTitle: function() {
return this.get('controller.tracks.firstObject.title');
}.property('controller.tracks.firstObject.title')
});
Then in your template, embed the player if this property is defined:
{{#if view.firstTrackTitle}}
embed code here
{{/if}}
FWIW I would put this logic in controller instead of view, but same idea.