How to specify which controller to use in a route in ember 2.0?
Default is that each route has its own controller and if I don't have code for a controller then a default empty controller is generated at runtime.
I want to specify that several routes share the same controller (and model). I see that in the documentation to an older version of ember it is possible to specify the controller with the "controllerName" property in the routes definition but that part of the documentation has been removed for the lastest ember version. And when I test the controllerName property it doesn't work.
It's not exactly what you are looking for but you could extend the controller that you want to use on the other routes.
import FooIndexController from 'ember-app/foo/index/controller';
export default FooIndexController.extend({});
You may also consider a mixin if you have a lot of code that should be shared by many controllers. It can be a much cleaner solution.
import Ember from 'ember';
import BaseController from 'ember-app/mixins/base-controller';
export default Ember.Controller.extend(BaseController, {
// Code specific to _this_ controller lives here
});
I figured it out. It turns out controllerName does work after all.
I just did this:
// route/home/books/book/details
import Ember from 'ember';
export default Ember.Route.extend({
controllerName: "home/books/book/index",
});
Then book and book/details shares controller. They already share model because the details route is a sub-route of book. So it works nicely.
Related
I am currently using ember 1.13. I have two apps which use emberjs. Now I am thinking of integrating these two apps by creating a new route in the first app and display specific route of the second app. Many suggested to use ember-engines,but they need ember 2.10 or higher.Since my application mostly depends on IE 8,I cannot migrate from ember 1.x.
So what should I do? Thanks in advance!!
Cheers!!!
So one approach that would work pre engines is to leverage an addon for the common routes. Your addon will define routes, controllers, and templates as usual with the addons directory. You will also want to define something like addons/utils/router-utils:
// assume we have a single route foo
export function addRoutes(router) {
router.route('foo');
}
router is the this value that ember provides when invoking Router.map. So, within your addon, to allow for "normal" feeling development, you'll want to use this addRoutes function within the dummy app router in tests/dummy/app/router.js:
import EmberRouter from '#ember/routing/router';
import config from './config/environment';
import { addRoutes } from 'addon-with-routes/utils/router-utils';
const Router = EmberRouter.extend({
location: config.locationType,
rootURL: config.rootURL
});
Router.map(function() {
addRoutes(this);
});
export default Router;
Note well, the above router.js file is what Ember 3.8 generates. Yours will most likely differ but the key point is that we invoke our addRoutes function with the anonymous Router.map this value to dynamically add our routes to the dummy app. See this twiddle for an example of adding routes to the router dynamically.
You can now run ember serve from within the addon project and test your routes. Acceptance tests run against the dummy app as well so you're not really constrained by this approach.
Now within your consuming app, you would do the same thing we did in the dummy app to add the routes. This approach, in general, though will require careful engineering to work effectively (a lot of the problems that ember engines solves must be solved by you in some way). Your addon will most likely have to expose a lot of configuration so that you can route outwards from the addon back into the consuming app which will not know about the routes in the consuming app. You'll have to avoid namespace collisions. Sounds fun though :)
I am brand new to EmberJS, and am going through a tutorial. I am at the part of the tutorial that starts talking about creating services and injecting them into your controllers (I'm not 100% sure if its a controller, but I'm coming from AngularJS, and it seems pretty similar).
In the terminal in my Ember project, I run the command ember g service authentication. I can see that the service was created in the services directory of my app in the file authentication.js. When I try injecting it into my controller however, I get this issue in the browser when I serve up the app locally,
Error: Assertion Failed: Attempting to inject an unknown injection: 'service:authentication
Could this be because I am using a version of Ember that is newer than in the tutorial, and there is a different way to inject services now? I ask that because this is the syntax of the service in the tutorial
import ember from 'ember'
export default Ember.Service.extend({
records: []
});
and this is the syntax of what I have now, auto-created when the project was built with ember new
import Service from '#ember/service';
export default Service.extend({
records: []
});
org.js "Where service is being injected"
import Route from '#ember/routing/route';
export default Route.extend({
authentication: Ember.inject.service(),
setupController(controller) {
this._super(...arguments);
}
});
Thanks you everyone for all the information about EmberJS.However It turns out all I needed to do was restart my local server -.-
In ember version 2.16, you can leverage javascript module api for importing.
Refer this blog post
Refer this full list
if your ember version is below 2.16, then
import ember from 'ember'
export default Ember.Service.extend({
records: []
});
if ember version is >= 2.16 then the below is the right way to import,
import Service from '#ember/service';
export default Service.extend({
records: []
});
Looks like you are using Ember 2.16 (as others have answered it uses the new components modularization and the tutorial you are following looks like 2.15 or prior, as you have also mentioned in your post).
It makes sense that you should use new modules in your new route too:
import Route from '#ember/routing/route';
import { inject as service } from "#ember/service";
export default Route.extend({
authentication: service()
});
One acclaration: the code you are showing is a route class (there are controllers on the route hierarchy, and also there are components that are not part of the route hierarchy). You will be able to inject your brand-new service in any of the mentioned levels.
I am using Ember.js 2.3 (and Ember-Data 2.3). I'm setting up a simple user auth process using Auth0. Nothing fancy yet, just installed Auth0 according to:
https://auth0.com/docs/quickstart/spa/ember2js/no-api
Now, my setup is pretty much exactly the same as the project given here. However, it seems that I can only access the session from application.hbs and not any other template. Or route. Or anything else.
So this handlebars snippet:
{{#if session.isAuthenticated}}
{{session.data.authenticated.profile.name}}
{{else}}
NOPE
{{/if}}
This works on application.hbs, but nowhere else. This does not make sense to me. If Auth0 itself says that session.data can be accessed from any template, and that such a handlebars snippet even exists, there must be something I'm missing. I need to be able to show certain portions of the client side as well as restrict some actions based on the currently signed-in user (and whether someone is actually signed in ), all of which are included in the session.data object.
It doesn't seem appropriate to pass this object to every component I'm going to create, and the only way I can think of getting this data right now is to manually get it from localStorage. I could perhaps make this manual process a mixin and have it included everywhere but before I try to find roundabout solutions, I want to make sure that I'm not missing something in the implementation itself.
How would I be able to access the session token throughout the application aside from application.hbs itself?
EDIT: Updating question in response to comments. My protected route looks like this:
import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
export default Ember.Route.extend(AuthenticatedRouteMixin, {
});
I am still unable to get session data, unfortunately.
In ember-simple-auth session is a service which You need to inject to the other routes. So if you want to use the session data other than the application template, you need to extend those routes with AuthenticatedRouteMixin
(just like you did in routes/home.js). In controllers you need to inject the service, for example:
// app/controllers/application.js
import Ember from 'ember';
export default Ember.Controller.extend({
session: Ember.inject.service('session')
…
});
Take a look at ember-simple-auth.
You can find another implementation if you check ember-simple-auth-token
Edit:
Try this in your routes/protected_route.js (it works for me)
import Ember from 'ember';
import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin';
export default Ember.Route.extend(ApplicationRouteMixin, {
session: Ember.inject.service('session'),
actions: {
invalidateSession: function() {
this.get('session').invalidate();
}
}
});
In my application I have common header that outlets into the main application layout. In that header you can select a site. I need that site selection to update another template that is rendered in the application layout. Having struggled with this for a few days I think the correct way to solve this is to use a shared service, to have the header controller observe the site selection and set that value in the shared service, then to have the index controller use a Ember.computed.alias on the value in the service controller. The following is an example of my code:
controllers/header.js
import Ember from 'ember';
export default Ember.Controller.extend({
sessionService: Ember.inject.service(),
currentSiteChanged: Ember.observer('session.current_site', function(){
var current_site = this.get('session.current_site');
console.log('currentSiteObserver', current_site);
this.get('sessionService').set('currentSite', current_site);
}),
});
controllers/index.js
import Ember from 'ember';
export default Ember.Controller.extend({
sessionService: Ember.inject.service(),
currentSite: Ember.computed.alias('sessionService.currentSite'),
dashboardData: function(){
var currentSite = this.get('currentSite');
console.log("in dashboardData", currentSite);
//other code that uses the currentSite
}.property('currentSite'),
});
services/session-service.js
import Ember from 'ember';
export default Ember.Service.extend({
currentSite: null,
setCurrentSite: function(){
var currentSite = this.get('session.current_site');
this.set('currentSite', currentSite );
}.on('init'),
});
I think this should allow someone to select a site in the header and have the dashboardData property in index update to use that selection. When the page initially loads the header defaults to the first site and the index renders it has the correct site value that it must have gotten from the session-service, however if you select another site the index does not get updated. Via the console.logs and debugging I can see that the header is observing the change and setting the value on the session-service.
Additionally I have tried solving this other ways (injecting the header service into the index and observing a property, injecting the index in the header and directly setting the value, sending and listening to events,etc) but I am willing to try anything or to be corrected that this isn't the correct way to solve the problem.
I am using ember 1.13.8 and moving to 2 isn't an option at the moment.
I don't think a service is an appropriate solution to this problem.
You want your application to have a good RESTful url design (respect for urls is a corner-stone of the Ember framework), so try to capture your application state in the URL.
Consider that if a user were to select a site, and then hit refresh they would lose their selection unless you stored it somehow in a cookie or localStorage.
I would recommend using either routes or query parameters to solve your problem.
Routes
Using routes is fairly straightforward (http://whatever.com/sites/pet-hampsters).
Query Params
You can also use query params, something like this http://whatever.com/?site=pet%20hampsters.
To do this you would write an action that bubbles up to your application controller and sets the value of the 'site' queryParam. Any of your sub-controllers on the currently active route can then read the site value with the new Ember.inject syntax. This is the conventional way to manage dependencies between controllers.
In the official Ember documentation is a section describing automatically generated controllers, once the model in a route has been set:
http://emberjs.com/guides/routing/generated-objects/#toc_generated-controllers
I wonder what would be the explicit code pendant to this process? In the doc it says "If you did not define it, one will be generated for you." and I assume, this does not happen in form of some auto-generated code, but in memory only.
Can someone show how the simplest version of an
ObjectController
ArrayController
Controller
would look like if you generated them in Ember-CLI by hand?
If you generated ObjectController, ArrayController and Controller by hand using Ember-CLI they would each be empty, as follows:
ObjectController:
import Ember from 'ember';
export default Ember.ObjectController.extend({
});
ArrayController:
import Ember from 'ember';
export default Ember.ArrayController.extend({
});
Controller:
import Ember from 'ember';
export default Ember.Controller.extend({
});
You can see the that these are the blueprints Ember-CLI uses to generate the controllers by checking the Ember-CLI source here.
You'll notice that the changeset I've linked to is removing the blueprints that generate controllers for the aforementioned controllers. I've done this to emphasize that Ember eventually be removing support for controllers following the 2.0 release. See the section entitled Routable Components in The Road to Ember 2.0 RFC.