Using template and controller multiple times on different routes in Ember - javascript

In my Ember application I have a categories controller and corresponding template.
I want to use this on various routes: When browsing, when advanced searching and when adding a product.
I tried to put it together as this:
#router
this.resource("categories", { path: "/*scope/select-category" }, function() {
} );
Scope could be 'search', 'products' or 'products/new'. It would make URLs very pretty!
But I'm having difficulties finding back the *scope value from my controller, I found it somewhere nested deeply, but with 'products/new' as the scope the value is 'products'.
Also I already experienced some strange behavior, for example, on a fresh page load for 'products/select-category' it wants to go to 'products.product', trying to find the product with ID='select-category'. Which is of course not what I want.
The categories route is the first route in the list so I assumed it would always pick that first..?
I'm doubting if this is the right way to do this.

You probably should do it this way, by handling the scope on a separate route:
#router
this.resource("scope", { path: "/scope/:scope" }, function() {
this.route("categories", { path: "/select-category" }
} );
This way you can handle scope nicely in the ScopeRoute, with a proper scope parameter.

Related

Dynamic view names in ui router states in AngularJS

I have a ui-view,
<div ui-view="filtersView_ModalA" class="filter-container"></div>
Now, I want to make generic routes, so that going forward, if any new filterView needs to be implemented like say,
<div ui-view="filtersView_ModalB" class="filter-container"></div>
My route can handle the same.
I am getting ModalA or ModalB from stateParams.prodType.
.state('Modal.tabs', {
url: .......,
views: {
'filtersView_{{stateParams.prodType}}#Modal.tabs': {
templateUrl: function(stateParams) {
// stateParams.prodType works here
.....
},
It's not working.
I also tried , 'filtersView_' + stateParams.prodType + '#Modal.tabs' : {
Nothing worked.
Or, can I declare a constant and concat the values in view names?
Am I doing something wrong?
No, you can't compose the view-name.
But you can do that using named views in different states. You can specify which component should be rendered in the view in which state. See more in the documentation: https://github.com/angular-ui/ui-router/wiki/Nested-States-and-Nested-Views
And also this entry: https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views

Using the same URL for multiple nested ember routes

I have a case using Ember where I want to make the top level URL available (ie. localhost:4200/demo), and have all the routes underneath also display the same URL (localhost:4200/demo). So the route file, if possible would look something like:
this.route('demo', function() {
this.route('one', { path: '/' });
this.route('submit', { path: '/' });
});
I understand that ENV.locationtype can be set for the whole app, but is there a way to conditionally set this for specific URLs underneath a parent URL?
Generally when you end up hitting major snags like this it is because Ember is implicitly trying to tell you that what you are doing isn't a good idea.
Is there a particular reason that you don't want your sub-routes to affect the URL in any way? Could you get by with random values in the URL if your prime purpose is to obfuscate things?
Ember uses the URL to work out what state things should be in in your app. If you don't want to use the routes at all you wouldn't have to, but then at that point you are dealing with a nested hierarchy of components that you have to switch between yourself. Which would in essence be akin to using React without a router ...
By default, Ember can manage URLs, or it can be set to not manage them, but it seems like the desired intent is to have it do both in a single environment, which is not logically allowed.
If none is declared for ENV.locationtype, then Ember's default URL management is turned off. This is an "environment-wide" configuration.
If the Ember Router is being used to map nested routes, and default URL management is in play, then observe that you cannot have the same URL path defined for multiple, sibling, child routes.
A further observation, is that your attempt above is tapping into functionality governed by the single index route that is available at every nesting level within the Router map. However, a route cannot have multiple index routes. Only the last one defined will be recognized.
Router.map(function() {
this.route('demo', function() {
this.route('one', { path: '/' }) // <-- this is over-ridden by "submit"
this.route('submit', { path: '/' }) // <-- this defines an "index" route for demo
})
})

insert component without calling handlebars helper or a controller with outlet

I want to insert a component into controller template without using the handlebars helper (component "component-name"... or component-name). Or through a controller in an outlet (or as long as the solution works for a component that wants to insert another component, then it's fine, I don't think outlets work in components).
In other words:
App.IndexController = Ember.Controller.extend({
actions: {
insertComponent: function() {
var component = this.container.lookup("component:my-inserted", { singleton: false });
component.set("layoutName", "components/my-inserted");
// to be like handlebars-inserted component, what do i do here?
}
}
});
You can use test with this: http://emberjs.jsbin.com/popozanare/4/edit?html,js,output
Why?
Thinking of a way of to have clean modal syntax, such as the "openModal" syntax described in the Ember Cookbook: http://guides.emberjs.com/v1.10.0/cookbook/user_interface_and_interaction/using_modal_dialogs/.
The problem is that the source context is lost, as the modal is within the ApplicationRoute. I want the same syntax when calling a modal, but keeping the hierarchy. You can keep the hierarchy using https://github.com/yapplabs/ember-modal-dialog, which requires a mapping of variables... which i don't like either (but will likely implement if I have no other choice).
TD;LR: Want to open modal within the controller/component (context) that called it without scaffolding in the controller/component that called it (mapping variables, etc).
Edit:
On second thought, using a container view might be cleaner than mapping variables, found in this solution: http://jsbin.com/hahohi/1/edit?html,js,output. Still needs scaffolding though. Thanks #user3568719.
That cookbook is a bit outdated, but if you are looking for a "clean" way to handling modals in your app I would suggest named outlets.
Add it to your application or auth template {{outlet "modal"}} and when you want to bring up the modal you can catch the action on the corresponding route and then render into that named outlet like so:
this.render('your-desired-modal-template', {
into: 'auth',
outlet: 'modal'
});
And when you want to dismiss it simply disconnectOutlet like so:
this.disconnectOutlet({
outlet: 'modal',
parentView: 'auth'
});
This is the way we've been going about it, I m open to suggestions/better methods.

emberjs using multiple paths / urls for one route

In Ember I can use this:
App.Router.map(function() {
this.route('accomodations');
});
so if one goes to /accomodations it will load that view.
I can also add:
App.Router.map(function() {
this.route('accomodations', { path: '/travel' });
});
so if one goes to /travel, it will go to the same view.
I want to be able to have /accomodations and /travel go to the same view? is this possible?
I know that this:
App.Router.map(function() {
this.route('accomodations');
this.route('accomodations', { path: '/travel' });
});
Will do what I'm asking, but if they go to accommodations, it should show that in the url, it always shows travel. I'm not even sure if the final piece of code is best practice.
You can simply interchange the two route-path definition lines:
App.Router.map(function() {
this.route('accomodations', { path: '/travel' });
this.route('accomodations');
});
The last definition takes the precedence for URL display in {{link-to ...'accomodations'}} and Route#transitionTo('accomodations') in-app transitions, though entering the app by '/travel' will leave the URL as is.
(EmberJS 1.11.3, 2.12.2)
Using redirection
In router.js
App.Router.map(function() {
this.route('accomodations');
this.route('travel');
});
In routes/travel.js
App.TravelRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('accomodations');
},
});
You do not have to put these in separate files (that's just where I would put them).
What this does is register two routes with the router. Pick one of them to be the "main" route, and the other the "alias" route. In this case, accomodation is the main route, and travel is its alias. When the user visits /travel, they get redirected to /accomodation.
This would be the default/ standard Ember way of accomplishing this, and if this sounds good to you, go for this.
Another possible solution
If you do not wish to have redirection happen, for some reason, and want the URL seen by the user to stay the same, but still display the same things, and behave in the same way, this is also possible.
In this case, you would create two of every single Ember unit (route, controller, view, template). The smart way would be to create a base class route, and have both App.TravelRoute and App.AccomodationRoute trivially extend it; create a base class controller, and have both App.TravelController and App.AccomodationController trivially extend it; same for views, if you have them.
Templates, OTOH, are a little trickier, because there is not way to extend them (that I know of). SO what you would need to do, is create either a partial or a component (decided which works better for you), and then reuse that partial/ component in both templates/accomodation.hbs and templates/travel.hbs

Angular ui-router: Can you change state without changing URL?

The multiple nested views functionality of the ui-router is very nice - you can easily jump from one state of your app to another.
Sometimes you might want to change the URL, but sometimes not. I feel like the concept of state should be separate/optional from routing.
Here's a plunker that shows what I mean. This is a fork of one of the plunkers in the ui-router documentation, with 2 minor changes noted below:
.state('route1', {
url: "/route", // <---- URL IS SHARED WITH ROUTE2
views: {
"viewA": {
template: "route1.viewA"
},
"viewB": {
template: "route1.viewB"
}
}
})
.state('route2', {
url: "/route", // <---- URL IS SHARED WITH ROUTE1
views: {
"viewA": {
template: "route2.viewA"
},
"viewB": {
template: "route2.viewB"
}
}
})
This seems to work - the URL stays the same. Again, how much redundant work is done here? Is this an approved/tested usage?
It would be nice if you could omit the url from a state..
UPDATE: You can omit a url from a state. plunker
Update question: Is this an approved/tested usage?
You can absolutely have a state without a URL. In fact, none of your states need URLs. That's a core part of the design. Having said that, I wouldn't do what you did above.
If you want two states to have the same URL, create an abstract parent state, assign a URL to it, and make the two states children of it (with no URL for either one).
To add to the other answer, Multiple Named Views do not use a URL.
From the docs:
If you define a views object, your state's templateUrl, template and
templateProvider will be ignored. So in the case that you need a
parent layout of these views, you can define an abstract state that
contains a template, and a child state under the layout state that
contains the 'views' object.
The reason for using named views is so that you can have more than one ui-view per template or in other words multiple views inside a single state. This way,
you can change the parts of your site using your routing even if the URL does not change and you can also reuse data in different templates because it's a
component with it's own controller and view.
See Angular Routing using ui-router for an in-depth explanation with examples.

Categories

Resources