Prevent error of missing handler in controller - ember.js

How can we normally prevent Nothing handled the action error in generic view implementation.
Currently I am reopening controller class and adding empty handler but again if I put it directly Ember throws deprecation message Action handlers implemented directly on controllers are deprecated if I add it in action object it is "not working" (probably overridden) and throws error as if it is not in base controller. Any ideas? Thanks.

If you want a somewhat hacky way to do it, you can add the method to the _actions object on the controller. That's where Ember internally keeps all of the actions for an object. Unfortunately, there's no other way to really handle an unused action from a view. This issue suggested a feature that would allow you to, but it hasn't been implemented yet.
Personally, I don't use straight views at all, I only use components. Components allow you to subscribe to particular events (let them bubble up) and ignore the others completely.

Related

Ember: Call a component action from a controller

I have a component working pretty well and now I need to call it inside a controller.
Scenario: I have an ember application, and I have an update button controller, I did a component that just display a toast(Materializecss) with some message I pass as parameter to the component and both the button and the toast are working well separately. I need to call inside the button controller this component to display to the user if the update was successfully or not using this component I did. Any sugestion of how can I call this component inside the controller? Thanks
have a look at the ember-twiddle I created and see if it fits the bill, in regards to what you want to do ?
You should instead of thinking "calling the component", rather, how can I push updated attributes/data to the component.
Ember relies on the "Data Dow Actions Up" pattern. This implies that you cannot make an explicit call to a component action from a controller. (see https://dockyard.com/blog/2015/10/14/best-practices-data-down-actions-up for example)
Instead, a better design should be to define a service to manage data : messages to be "toasted". Then make this service available by injecting in in your controller. You will be able to call methods to register a new messages and generate new data.
Provide also a component template (to be included in your own templates) that will be in charge to display the new message, etc. Each change in the data managed by the service will lead to a component template update.
You should definitely take a look to https://www.npmjs.com/package/ember-toastr

How to invoke an controller action in ember.js

I am rendering charts(based on highcharts) using ember. I want to invoke a function on clicking a point. I have defined this function inside my ember component. See jsfiddle link below:
{} http://jsfiddle.net/qmmvx/67/
On clicking a point, I get an error which indicates App.ChartComponent is null.What is it that I am missing here?
Not sure if using App.__container__.lookup here is the smartest way, but replacing App.ChartComponent.test(); with App.__container__.lookup('component:chart').send('test') solves your problem. send is used to invoke any method from actions.

What is the craic with ContainerViews? (Assertion Failed: calling set on destroyed object)

All,
I have searched around for an answer to this but have yet to find a good explanation and solution. Hopefully, you can help.
I have a route that renders an Ember.ContainerView (as opposed to a standard Ember.View). When I transition away from this route and then back to it (either via the back button, a link-helper or just changing the url) I get the following error in the console:
Uncaught Error: Assertion Failed: calling set on destroyed object
I understand that a high level reason for this is that when we transition away from the route with the ContainerView, it's childViews are marked as destroyed. When we transition back to the route, the problem has something to do with Ember trying to set the childViews back to the destroyed instances.
I'm not exactly clear but that is the vague understanding I currently have.
So, my questions are as follows:
Can you please correct my understanding of this problem if it is not correct?
Can you please tell me how to fix this error?
For your convenience, I have created a JSBin example for your viewing pleasure. To replicate the error, open your JS console, click on the Go to Route two link, then click on the Go to index link. Now check your logs.
Thanks in advance for any assistance you can provide.
Here is the fix: http://jsbin.com/jumoy/1/edit?html,css,js,output
I have encountered this problem before. I can't say I truly understand it at a very detailed level, but here is the general problem. When you are defining your container view, it is actually creating that subview when you define it, not when you create an instance of the view. This means that your childview 'initial' is only being created one time, and thats when the file is initialled parsed and the ContainerView is defined. When ember cleans this childview up, it is not gone for ever and 'initial' will always be equal to a cleaned up view.
By setting 'initial' as a property, it will be created every time a new instance of your container view is rendered, and therefore a new childview will be created and accessible.
So moral of the story, try not to create objects in definitions of controllers/views. Instead create properties that return the creation of that object.
Hope this helps and makes sense.
UPDATE::
I have edited the jsbin to show you on a deeper level what is happening and why it isn't working. To see the effect uncomment the second ContainerView and comment out the first, you will notice in the console logs that the second time you go to the twoRoute, it has marked that initial property as state: destroying for the view.
http://jsbin.com/jumoy/2/edit?html,js,output
if you are using Ember.Instrumentation namespace for publishing your events and Ember.subscribe to listen to them in your code, when you publish events, it stack all the subscribers and call them even when they are destroyed.
so basically, when for example your route is destroyed which is running subscribe statements it will fail and give above error.
Here is a solution to this problem: Use Ember.Instrumentation.reset() to remove previous subscribers which are destroyed. This solution helped me in acceptance tests where app was destroyed after tests are finished.
I wrote Ember.Instrumentation.reset() in startApp function of module-for-acceptance.js and it worked.
Hope that helps.

Child controller observers still active after route change

I'm currently working on a map application with EmberJS, using ember-leaflet for displaying the map. See this jsFiddle for my current setup:
http://jsfiddle.net/HUnnr/1/
My problem is, that I didn't get the click event delegated to the PlacesNewController, only if the /places/new route is open.
my first attempt
Delegating the click event from MapView -> PlacesController -> PlacesNewController, but that did also handle the click event and add a marker to the map, after I changed the route, because PlacesNewController was still alive.
my second attempt
Then I tried Embers Evented mixin. After I had delegated the event from MapView -> PlacesController, I triggered an event. I bind PlacesNewController to this event on PlacesNewRoute.activate and unbind it on PlacesNewRoute.deactivate. The main problem was, that I couldn't access the model of PlacesNewController from the event handling function.
Both solution above doesn't seem to be the "ember way". I think there is a better solution for something like this. Maybe someone could help me to solve this problem. I think, something like direct delegating map events to PlacesNewController would be the cleanest solution, but I didn't know how I could achieve that with Ember.
EDIT:
Here is a new jsBin:
http://emberjs.jsbin.com/uHOPOfi/23/edit
The main problem is, if you first visit /places route, as expected the observers for zoom and isCloseEnough are not called. After that you go to /places/new and the observers are working as expected. But what I didn't understand is, why after going back to /places, the observers and with them also the PlacesNewController are still active? I thought Ember
send an action to the controller.
You can bounce actions around through controllers.
(sorry, switched to jsbin, jsfiddle doesn't fit well on my screen)
http://emberjs.jsbin.com/AguxORAD/3/edit
Personally I'd ditch the new route/controller, it seems weird since all of the real logic lives in places and you'll have to proxy info back and forth, but that's up to you.
I have found a good solution for this problem with the hints from kingpin's answer and this video. The main point is, that every event from the view hits the current route. So the map always delegates the click event. But then it could be processed route depended in PlacesRoute or PlacesNewRoute. So the PlacesNewController does all the place creation logic, the PlacesController does index logic and so on. I think that's a good starting point at the moment.
Here a jsFiddle, that shows my current solution described above.
#kingpin: thank you for your help

TransitionTo and the new Ember Router

The new ember router has been throwing me for a loop. Does anyone know how to manually triggering a url change when you are (1) NOT using a redirect in the router (2) NOT using the linkTo helper?
It seems that this:
App.container.lookup('router:main').router
no longer works, as of today's build.
This seems hard to do in new ember router because ember is working hard to prevent you writing code in this style. Rather than access an instance of the router (or anything else) via App your ember application code should be working with properties that have been injected at runtime by the framework. As #sly7_7 mentioned above, your view will have access to the controller and controller can trigger a transition like:
view.get('controller').transitionTo('state')
Depending on how your third party library is working, you might do this by triggering an event in the dom (handled by the view) or by registering a callback when the view is rendered from within didInsertElement
The main thing to remember is that App.anything-in-lowercase is generally bad practice. Whenever possible try to let the framework take care of instantiating and wiring together your application classes.
For more detail, see the notes on this commit: https://github.com/emberjs/ember.js/commit/5becdc4467573f80a5c5dbb51d97c6b9239714a8
You can try this:
App.__container__.lookup('router:main').transitionTo('name_of_your_route');