How to add base class for built in objects (for example controller, router, ...) in ember?
I need to add properties in all controllers and other objects. When I created my controller, I extend from MyBaseController, but built in controller is extended from Ember.Controller. How to force built in controllers extend from MyBaseController?
If you need to add properties to all instances of a class, you can use reopen and reopenClass features.
To read more, have a look this page from ember guides.
Related
I am trying to make a pagination component for ember 2 app.
Since it is a general purpose pagination component, I wanted to use it on many different routes. Because of that I need to somehow (in my mind) provide a name of my route for pagination links to work.
I can pass in my route name (string) to the component easily:
{{pagination-component myRoute='myCurrentRouteName'}}. And
inside of component: {{link-to myRoute (query-params page=1)}}
It works well for going to pages like: << First, < Previous, Next > , Last >>.
But I also wanted to have a select box with options pointing to all the pages, where if user selects a page, I can transition into that route with queryParams similar to this: myRoute?page=selectedPage.
All the tutorials for ember say that transitioning within the component is a no-no.
But how do I do it instead, given that I want my pagination to be generic and I don't want to have action within every single route that deals with pagination and provide same exact transitioning?
So far I found that I can inject the '-routing' into the component, which can work for transitioning within the component, but it also doesn't quiet work for some reason. Plus people say that it is private and unreliable.
I also tried making a Route Mixin with action so I can simply sendAction from the component with the selectedPage, but I don't know how to get the router (in order to call router.transitionTo) within my Mixin.
We should use public API for transitioning, that is provided in Route transitionTo and in Controller transitionToRoute. this is the recommended approach.
As you said, you can make it work in the component using Ember.getOwner(this).lookup('router:main').transitionTo('myRouteName') but that's strongly against good design.
You can define method named myTransitionToUrl inside actions hash of the Application route, and install ember-route-action-helper addon to call route action method myTransitionToUrl from component.
If you don't want to define method in application route, then you can define it in mixin and implement it in the required route. that's also will work.
My choice and Recommended approach would be, Say pagination-component has prev,next,transtionTo actions, then I will implement all those actions in Mixin and extend it in all route which uses pagination-component. and will inform any data changes to route through actions from component. that will ensure Data Down Actions Up strategy too.
If you are just transitioning to a different route, then the Latest possible way is,
If ember version is greater than 2.15, then you can inject RouterService and and call transitionTo method directly.
If you are using the ember version 2.15 or below, then you can use the router service polyfill to use RouterService.
import Ember from 'ember';
export default Ember.Component.extend({
router: Ember.inject.service(),
actions: {
next() {
this.get('router').transitionTo('other.route');
}
}
});
When using globals we could have defined App.Controller, App.ObjectController and App.ArrayController to control what class Ember will use to generate controllers.
With EmberCLI, I see documentation for routes - using app/routes/basic.js. This works fine.
Does it also work for views? What about controllers? How would I implement the 'basic' for each kind of controller?
Yes, this works for just about any object Ember would generate, including controllers. If you look here you can see that Ember looks for 3 different types of controllers to generate: basic, object, and array. You can override these defaults by creating the following files:
app/controllers/basic.js
app/controllers/object.js
app/controllers/array.js
Ember is moving away from views and controllers in favor of components. (See the Routable Components section of The Road to Ember 2.0.) To that end, I don't believe Ember-CLI provides the ability to provide a basic implementation of each of these controllers in order to discourage their use. (At least I could not find anything from searching the code base.)
There are times when you use App.Model.reopenClass() on a model (link) and the Ember guides talk about App.Router.reopen() (link). From the Ember guides:
reopen is used to add instance methods and properties that are shared
across all instances of a class. It does not add methods and
properties to a particular instance of a class as in vanilla
JavaScript (without using prototype).
But when you need to create class methods or add properties to the
class itself you can use reopenClass.
When is this necessary/advantageous? Is it not possible to just add everything right up front?
reopenClass is analogous to adding methods to the prototype instead of adding methods on each and every instance of your classes. You can think of them as static variables/methods, instead of instance variables/methods.
It's a major performance gain, and possibly makes more sense for the problem you are solving.
One example where you would reopen a class is that when you want to add properties to an existing default generated class. For example: many instances of ember applications don't extend router class. They just use default router class. But what if you want to add some properties to router class that you want to use somewhere else. reopen is pretty usefull there. This is one use case I can think of.
Also, In the case of Router extending the class is difficult as most of the code within ember just uses router class. Even if you extend, some callbacks/closures will still refer to the older router class.
I have an existing DetailController and DetailView in my app that has some pretty complicated UI / data manipulation logic (hotkeys, copy paste, duplication, autocomplete, etc) -- the view sends UI events to the controller; the controller handles the logic.
I want to convert this to an Ember component.
Does this basically mean I merge the view and controller into DetailComponent? This seems messy and wrong to me.
If not, how do I use controllers and views internally within a component? That is, I still want the complete isolation and well-defined public interface of the component, but internally within the component, I'd like to use controllers and views for organization. Is that possible?
Is it possible to use {{render}}, {{view}}, {{partial}} within the component template?
Does this basically mean I merge the view and controller into DetailComponent? This seems messy and wrong to me.
Yes that is what it means.
internally within the component, I'd like to use controllers and views for organization. Is that possible?
So component basically replaces a single view/controller pair. Beyond that a component is just an extension of Ember.View and can be organized just like any other view.
Is it possible to use {{render}}, {{view}}, {{partial}} within the component template?
Yes. Any of those helpers will work.
In previous versions of Ember, I used a singular PostController to manage new/show and edit views.
But now with the separation of controllers and routes and the convention of using post.new/post.edit/post controllers, I'm not sure what the convention for sharing the logic across views.
Bear in mind my edit/new routes aren't nested inside the posts route because the outlets aren't nested so I can't put the logic in a parent route.
Do I override the controller in the route and use my old singular controller?
Do I use {{with controllers.post}} block inside the handlebars template?
Do I use a shared mixin between PostNewRoute/PostEditRoute and PostNewController/PostEditController?
Do I inherit PostEditController from PostNewController?
Wrap all the post routes inside a route who's template is simply {{outlet}} so I can inherit shared events?
Something else I've missed?
I doubt there's a proper convention for this yet, but I'd like to hear how other people are doing it?
Use the render helper:
https://gist.github.com/dagda1/4758119
Then you can use the model hook in the router to either create the record or retrive it in the route:
https://gist.github.com/dagda1/4758144