Ember send action from component to context controller - ember.js

In the case below videoEnded function is successfully called, however how do I get a reference to the actual Ember component it self?
export default Ember.Component.extend({
videoEnded: function(){
var self = this;
alert('how do i get a reference to the actual ember component object here ?')
}
didInsertElement: function() {
var self = this;
var options = {};
self._soundjs = soundjs('soundOne', options, function(){
});
self._soundjs.on('ended',self.videoEnded);
}

The following solved my issue. videEnded callback was losing the components context. The following code resolved the issue, self passed to video ended refers to the component context which can then be used, to send actions to the context controller.
self._soundjs.on('ended',function() { self.videoEnded.apply(self, arguments); });
Credit: #teddyzeenny

Related

How to reference a model in Ember.js?

I am working through toDoMVC and in the code below, just don't quite understand what this refers in var model = this.get('model');.
Does it refer to Controller or Route. If it is Controller, then where do we declare that Model x works with Controller y?
Todos.TodoController = Ember.ObjectController.extend({
isCompleted: function(key, value){
var model = this.get('model');
...
}.property('model.isCompleted')
});
I. Usually this variable inside Ember.Object functions refers to an instance of that Ember.Object (an instance of Todos.TodoController in your case).
Example:
App.SomeRoute = Em.Route.extend({
activate: function() {
this; // this is App.SomeRoute instance ref.
}
});
App.SomeController = Em.Controller.extend({
someMethod: function() {
this; // this is App.SomeController instance ref.
}
});
App.SomeView = Em.View.extend({
someMethod: function() {
this; // this is App.SomeView instance ref.
}
});
and so on.
II. this.get('model') is just a property of controller (you can set any value to that property if you want). *Before ember v1.7 model was an Ember.computed.alias to controller's property named content, but this behavior was changed in latest ember's versions.
There is another model property, in Em.Route, it differs from Em.ObjectController.model property. Actually, it's a function invoked in routing (transition) sequence, which returns data, which Em.Route uses to set a controller.model property in setupController hook of Em.Route. So, output of this.get('model') inside of Em.Route's methods will be a function.
P.S. I tried not to screw up with tenses, but most likely I didn't succeed.:) I'am sorry.

Ember-Data "TypeError: this.container is undefined"

I'm trying to load the current user into the data store but am having some difficulty. The server uses PassportJS and visiting /api/users/me returns a JSON object similar to this:
{"user":{"_id":"53a4d9c4b18d19631d766980","email":"ashtonwar#gmail.com",
"last_name":"War","first_name":"Ashton","location":"Reading, England",
"birthday":"12/24/1993","gender":"male","fb_id":"615454635195582","__v":0}}
My store is just defined by App.store = DS.Store.create();
The controller to retrieve the current user is:
App.UsersCurrentController = Ember.ObjectController.extend({
content: null,
retrieveCurrentUser: function() {
var controller = this;
Ember.$.getJSON('api/users/me', function(data) {
App.store.createRecord('user', data.user);
var currentUser = App.store.find(data.user._id);
controller.set('content', currentUser);
});
}.call()
});
It is called by my application controller:
App.ApplicationController = Ember.Controller.extend({
needs: "UsersCurrent",
user: Ember.computed.alias("controllers.UsersCurrent")
});
I suspect the line App.store.createRecord('user', data.user); is causing issues but I don't have any idea how to fix it.
The console logs TypeError: this.container is undefined while the Ember debugger shows every promise is fulfilled and the users.current controller has no content. Thankyou for any help you can provide.
Are you defining the store on the App namespace, because Ember Data doesn't do that by default. Either way, you're failing to define the type you want to find after you create the record.
var currentUser = controller.store.find('user', data.user._id);
createRecord returns the record, so there is no point in finding it afterward
var currentUser = controller.store.createRecord('user', data.user);
Also in your example, you are trying to call the function immediately on the type, and not on the instance. You should add that as a method to run on init.
App.UsersCurrentController = Ember.ObjectController.extend({
retrieveCurrentUser: function() {
console.log('hello')
var controller = this;
Ember.$.getJSON('api/users/me', function(data) {
var user = controller.store.createRecord('user', data.user);
controller.set('model', user);
});
}.on('init')
});
http://emberjs.jsbin.com/OxIDiVU/693/edit

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.

Why can't this Emberjs controller set a key

Below is a reduced Ember controller. jQuery is used to make a remote call, and action needs to be taken in the controller in the callback.
In the callback, this refers to the GenericController correctly, I can read a value with this.get('someKey') but this.set('someKey', '') will not set the value. This works when the this.transitionTo method is removed. Any help on how to get the set to work with a transition present would be super helpful.
App.GenericController = Ember.Controller.extend({
someAction: function() {
var jqxhr = jQuery.getJSON(this._endpoint, {someKey: this.get('someKey')});
jqxhr.done(this._someActionComplete.bind(this));
},
_endpoint: '/some/generic.json',
_someActionComplete: function(json, textStatus, jqxhr) {
this.set('someKey', '');
this.transitionToRoute('reference', reference);
}
});
It' all about async.
When you invoke your method this correctly references the controller as you already noticed, this is why you can use this.get('someValue'), but by the time the ayncronous call returns (wenn done is invoked for example) this no longer references your controller anymore but the object which invoked the done function, so you have to safe the correct reference to this before you make the request, this way you can use it to pass it to the bind function:
App.GenericController = Ember.Controller.extend({
someAction: function() {
var _this = this;
var jqxhr = jQuery.getJSON(this._endpoint, {someKey: this.get('someKey')});
jqxhr.done(_this._someActionComplete(_this));
},
_endpoint: '/some/generic.json',
_someActionComplete: function(json, textStatus, jqxhr) {
this.set('someKey', '');
}
});
Update in response to your last comment
I don't know what you are doing differently, but take a look at this simple Demo that it works as expected. Click the button "Some action" to execute the request.
Hope it helps.
Because this in jqxhr.done does not reference the GenericController, it references the object that invoked done. This is how I solve it:
App.GenericController = Ember.Controller.extend({
someAction: function() {
var self = this;
var jqxhr = jQuery.getJSON(this._endpoint, {someKey: this.get('someKey')});
jqxhr.done(self._someActionComplete.bind(self));
}
}
Now you still have a reference to this you can use to call other functions, including set, on the controller.

How to get any controller instance from init() method of a view?

I am migrating my project from older version of EmberJS. In some places i used to get controller instance which is not related to the view, by using following in any view's init() method:
var controller = App.get('router').get('firstController');
But now this throws following error.
Uncaught TypeError: Cannot call method 'get' of undefined
This may be because it is not able to get the Router object. Now how to get controller instance which is not related to the view? or how to get the Router Object
The 'needs' feature allows a controller to access to other controllers, which allows a controller's view to access other controllers. (a good explanation of needs in Ember: http://darthdeus.github.com/blog/2013/01/27/controllers-needs-explained/)
As explained in Cannot access Controller in init function of View in 1.0.0rc, the controller property of a view is not yet set when init() is called, so you will need to access controller at a later time in the view's life cycle. This could be the willInsertElement() or didInsertElement() hooks, for example.
Here is an example demonstrating using needs access another controller from a view:
http://jsbin.com/ixupad/186/edit
App = Ember.Application.create({});
App.ApplicationController = Ember.Controller.extend({
doSomething: function(message) {
console.log(message);
}
});
App.IndexView = Ember.View.extend({
templateName: 'index',
init: function() {
this._super();
// doesn't work, controller is not set for this view yet see:
// https://stackoverflow.com/questions/15272318/cannot-access-controller-in-init-function-of-view-in-1-0-0rc
//this.get('controller.controllers.application').doSomething("from view init");
},
willInsertElement: function() {
this.get('controller.controllers.application').doSomething("from view willInsertElement");
},
clickMe: function() {
this.get('controller.controllers.application').doSomething("from clickMe");
}
});
App.IndexController = Ember.Controller.extend({
needs: ['application']
});