I have the following router setup in Ember where I am trying to capture a dynamic search term and pass it to the router for querying ember-data.
Router
this.resource('resources', function() {
this.resource('resource', { path: '/:resource_id' }, function() {});
this.resource('search', { path: '/search/:search_term' }, function() {});
this.route('new');
});
Route
export default Ember.Route.extend({
model: function(params) {
return this.store.findQuery('resource', {
sTerm: params.search_term,
limit: 15,
offset: 0
});
}
});
Unfortunately, search_term in not available in the route to pass into the query, I am unsure what is causing this not to work. If someone can point me in the right direction I would sure appreciate it. Thanks.
Update as requested
Logging this.constructor produces the following:
lrs-ui#route:search/index:
I have built this with ember-cli and the route is in search/index so this makes sense. Should I just have the route at search maybe?
Answer
As #kingpin2k led to, the route was in search/index and it needed to be in search, then everything worked just fine.
For historical sake, the index route doesn't pick up the params from the parent resource.
Changing the route from search/index to search fixed the issue.
Related
I have an ember application (version 3.14) which I'd like to do a transition to a Route with dynamic segment
I'd like to redirect to /projects/other/2020 when user visits /projects/other
I change my projects/other route so it looks like this but it throws me an error
import Route from '#ember/routing/route';
export default Route.extend({
model: function(){
},
redirect() {
let year_data = {
year: '2020'
};
this.transitionTo('projects.other',year_data);
}
});
and this is how my projects route looks like in routes.js
this.route('projects', function() {
this.route('notable',{path: '/'});
this.route('other', function() {
this.route('list', {path: '/:year'});
});
});
these are the errors from google chrome console box
error screenshot
Error message is pretty clear. You are trying to redirect to projects.other.index route which does not have any dynamic segments. Also, according to docs, you need to pass an id and not an object. When you pass an object, ember treats it like ready to use model. So, your code should be
this.transitionTo('projects.other.list', '2020');
What is the difference between router and route in emberjs? I wanted an implementable explanation if possible
Router - ember application will have one Router, it manages transitions between routes and it contains map of all routes. You specify map of routes like so:
App.Router.map(function(){
this.route('post', { path: '/post/:post_id' }, function() {
this.route('edit');
this.route('comments', { resetNamespace: true }, function() {
this.route('new');
});
});
});
from which Router is able to identify structure of routes and their accepting params. It activates corresponding Route when you navigate to particular path/url in browser ember router docs
Route - for each path/route you will have Route object, when you change path/url in browser corresponding Route gets activated for that path and set up everything (controller, template) which relate to that route (that has same name usually).
ember route docs
read more
The practical difference between these two is that resource may contain other routes, whereas route cannot. Additionally, this.resource automatically creates an index route when it sees you have sub-routes.
App.Router.map(function() {
this.resource('records', function() {
// this.route('index') is created automatically in here
this.route('new');
});
this.route('about');
});
While you could always use this.resource and have things work correctly, this.route explicitly creates router leaf states and therefore will lead to a more precise and efficient graph of states for your app.
I have a need for deep nesting some routes in ember, I have something like this.
this.resource('wizards', {
path: '/wizards'
}, function() {
this.resource('wizards.google', {
path: '/google'
}, function() {
this.resource('wizards.google.register', {
path: '/register'
}, function() {
this.route('step1');
this.route('step2');
this.route('step3');
this.route('summary');
});
});
});
What I was expecting was as structure like this:
url /wizards/google/register/step1
route name wizards.google.register.step1
route Wizards.Google.Register.Step1Route
Controller Wizards.Google.Register.Step1Controller
template wizards/google/register/step1
but I got this:
url /wizards/google/register/step1 //as expected
route name wizards.google.register.step1 //as expected
route WizardsGoogle.Register.Step1Route
Controller WizardsGoogle.Register.Step1Controller
template wizards/google.register.step1
What I don't get is when does ember stop using capitalization (WizardsGoogle) and start using namespaces (WizardsGoogle.Register). The seemingly inconsistency confuses me. I would have expected either of them.
I met the same things with deep nested resources. Although I didn't know how this happens, what I can tell is that you can always use CapitalizedNestedRoute without namespace, and Ember can recognize it. Although in Ember Inspector it displays "WizardsGoogle.Register.Step1Route".
In your example I defined such route:
App = Em.Application.create();
App.Router.map(function() {
this.resource('wizards', function() {
this.resource('wizards.google', function() {
this.resource('wizards.google.register', function() {
this.route('step1');
this.route('step2');
this.route('step3');
});
});
});
});
App.IndexRoute = Em.Route.extend({
beforeModel: function() {
// Transition to step1 route
this.transitionTo('wizards.google.register.step1');
}
});
App.WizardsGoogleRegisterStep1Route = Em.Route.extend({
model: function() {
// You can see this alert when you enter index page.
alert('a');
}
});
In this example the app will transition to WizardsGoogleRegisterStep1Route with no problem. And if you use container to find route like this:
App.__container__.lookup('route:wizards.google.register.step1').constructor
It will also display App.WizardsGoogleRegisterStep1Route. It's the same as Ember Guide describes. http://emberjs.com/guides/routing/defining-your-routes/#toc_nested-resources And Ember Guide doesn't introduce namespace route.
So I think it's better to according to what Ember Guide suggests (always use CapitalizedNestedRoute). And in my opinion it's easier to define CapitalizedNestedRoute than nested.namespace.route.
Finally, if you really want to use namespace route/controller/template, you can have a look at Ember.DefaultResolver. Check the API to learn how to extend it so container can lookup modules by your own rules.
Routes are "namespaced" inside resources. And resources uses what you call capitalization, where they sort of define a namespace (for routes to use).
So this set of routes:
App.Router.map(function() {
this.resource('posts', function() {
this.route('new');
this.route('old');
this.route('edit');
this.route('whatever');
});
});
Would result in routes with the following name:
PostsRoute
PostsNewRoute
PostsOldRoute
PostsEditRoute
PostsWhateverRoute
Whereas, the following set of routes:
App.Router.map(function() {
this.resource('posts', function() {
this.resource('photos');
this.resource('comments');
this.resource('likes');
this.resource('teets');
});
});
Would result in route with the following names:
PostsRoute
PhotosRoute
CommentsRoute
LikesRoute
TeetsRoute
Also note, that resources within resources don't get "namespaced" to the "parent" resource, so you'll always ever have the form:
{CapitalizedResourceName}Route // for resources
{CapitalizedParentResourceName}{RouteName}Route // for routes
I hope this helps you!
I have a route that catches all missing routes and renders a 404-style page. I would like to create a route that matches any url starts with "/browse/" such as "/browse/shoes/red". This seems like the correct way to do that:
App.Router.map(function() {
this.route('browse', { path: '/browse/*fields' });
this.route('missing', { path: '/*badPath' });
});
However, ember's RouteRecognizer always picks the missing route over the browse route. (The logic that does this is in sortSolutions of route-recognizer.js .) Is this a bug in Ember? Is there a right way to use glob routes and still have a 404 handler?
By the way, I can create a resource for browse instead of making it a route like this:
App.Router.map(function() {
this.resource('browse', { path: '/browse' }, function() {
this.route('baz', {path: '/*'});
});
this.route('missing', { path: '*' });
});
This still has the same problem.
I think this must be a bug...
Here's a JSBin : http://jsbin.com/ucanam/1403/edit
Here you can see it going directly to the 'missing' route as expected:
http://jsbin.com/ucanam/1403#/some/random/stuff
And a failed attempt at going directly to a 'browse' route :
http://jsbin.com/ucanam/1403#/browse/test/stuff
I am currently trying to migrate my Ember based on pre1 to the current release pre4. In my pre1-code, i defined a route as follows:
formCreated : Ember.Route.extend({
route : '/genre=:genre/sorting=:sorting/location=:location/range=:range/time=:date/:timeFrame',
....
})
This Route worked fine for me, but now i am struggling to mimic this behaviour with pre4. This is my approach:
App.Router.map(function() {
this.route("/");
this.route("formCreated", { path: "/genre=:genre/sorting=:sorting/location=:location/range=:range/time=:date/:timeFrame" });
});
App.FormCreatedRoute = Ember.Route.extend({
serialize: function(context, params){
// here i am returning a hash containing all the dynamic segments
}
});
What is going wrong?
When the App enters the state, the URL does not get updated properly. I am seeing this result:
/genre=:genre/sorting=:sorting/location=:location/range=:range/time=:date/6:00-19:00
So most of my dynamic segments do not get updated. I made sure that my custom serialize method is returning an appropriate hash object, where one property for each dynamic segment is set.
Are multiple dynamic segments per route still possible with pre4 or do i have to switch to some route nesting approach or something like that?
UPDATE: Root cause found:
I just discovered that the error happened because of the syntax i used for the route. I changed it to the following(replaced the "=" with "/"):
this.route("formCreated", { path: "/genre/:genre/sorting/:sorting/location/:location/range/:range/time/:date/:timeFrame" });
Is there any documentation on how the path may be structured? It seems that syntax has changed since ember-pre1. I would like to have a user friendly URL and those numerous Slashes make it difficult to read. Or is the rule, that a segment always has to start with ":/"?
You will need to use resource nesting, like described here and here
App.Router.map(function() {
this.route('/');
this.resource('genre', { path: '/genre/:genre_id' }, function(params) {
this.resource('sorting', { path: '/sorting/:sorting_id' }, function(params) {
...
});
});
});