In 1.7 Ember should support Query Parameters. I have no problems using them in controller but I'd like to access them in Route, ideally in beforeModel hook but model hook would work as well.
The API docs mention a queryParam parameter for the beforeModel hook but if I try to use it, it is always undefined.
The Query Parameters guide seems to suggest that the query parameters should be accessible as a part of the first parameter to the model hook. But that is also undefined. See the code below for examples.
Is there a way to access the query parameters from Route?
Thank you for your help.
App.ApplicationRoute = Em.Route.extend({
beforeModel: function(transition, queryParams){
console.log(queryParams.test); //undefined at /?test=123
},
model: function(params){
console.log(params.test); //undefined at /?test=123
}
});
Pretty sure it's a bug, but you can access them in the meantime via the transition object:
App.ApplicationRoute = Em.Route.extend({
beforeModel: function(transition){
console.log(transition.queryParams.test);
}
}
By specifying the query params in the controller, params will contain them automatically
ApplicationController = Ember.Controller.extend({
queryParams: ['test'],
test: null
});
In the latest version of ember (2.12 at the time of writing this answer), queryParams can be accessed in the model hook as follows:
import Ember from 'ember';
export default Ember.Route.extend({
queryParams: {
test: ''
},
model(params) {
console.log(params.test);
},
});
Observe that now both dynamic segment and queryParams are accessible via the params object. Since params is not available in the beforeModel hook, this solution works on when you have to access the queryParams in the model hook.
In latest ember version you can get the value in Route as
import Ember from 'ember';
export default Ember.Route.extend({
beforeModel(params){
console.log(params.queryParams.test); //if the parameter contains test as the key
}
});
This works only if the locationType is auto in your environment.js file.
If you want to access in didTransition action,
didTransition: (queryParams) ->
console.log(#get('queryParams'))
Related
I am building a Ember Application where I fetch a feed of Debate objects from an API end point in a route, via the following ajax call:
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
$.getJSON("http://localhost:3000/api/v2/debate_feed").then(debates => {
store.push(debates);
});
}
});
Upon receiving the Debate objects I need to save them to the data store, the problem is I can not access the Ember Data store after the ajax call is complete. When I try to access the store I get the following error:
Uncaught ReferenceError: store is not defined(…)
Any ideas what the issue is?
store is not defined in the Route. You can this.get('store') to get store object. You can try the below code.
import Ember from 'ember';
export default Ember.Route.extend({
beforeModel(transition) {
return Ember.$.getJSON("http://localhost:3000/api/v2/debate_feed").then(debates => {
this.get('store').push(debates);
});
},
model: function() {
return this.store.peekAll('debate');
}
});
But the preferred approach is,
1.Define debate model model guide
2.Define Adapter - JSONAPIAdapter or RESTAdapter.adapter guide
3.Implement API end point for GET request /debates
then you can just simply say this.store.findAll('debate') this will fetch and update it to store.
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.findAll('debate');
}
});
It should be this.store.push(...), but you really should implement the ajax call with an adapter! Also notice that the model will be empty, because you return nothing. If you want to have the model do return this.store.push(...).
Pretty new to Ember so maybe someone can help me out. I keep running across this error and have no idea how to solve it.
Ember : 2.5.1
Ember Data : 2.5.3
Below is my router.js.
//app/router.js
import Ember from 'ember';
import config from './config/environment';
const Router = Ember.Router.extend({
location: config.locationType
});
Router.map(function() {
this.route('organization', {path: '/organization/:id'}, function(){
this.route('about', { path: '/about' });
this.route('admin', { path: '/admin' }, function(){
this.route('team', { path: '/team/:team_id' });
});
});
});
The organization/:id/about and organization/:id/admin routes work fine. But when I try to load the organization/:id/admin/team/:team_id route, the error is thrown. Below is the routes/organization/admin/team.js file:
//app/routes/organization/admin/team.js
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
let organization = this.modelFor('organization');
return organization.get('team');
}
});
Not really sure what other information I should post, so please ask for any additional information you may think is necessary to help debug. My guess is it's something pretty simple and I'm completely oblivious to it.
EDIT
I've added a couple more files to help diagnose the problem:
//app/routes/organization.js
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
return this.store.findRecord('organization', params.organization_id)
}
});
//app/routes/organization/admin.js
import Ember from 'ember';
export default Ember.Route.extend({
actions: {
changeValue(){
this.currentModel.save();
}
}
});
Where currentModel is the model for the organization route. I've removed the organization.admin.team model hook for now and am just testing a
{{#link-to 'organization.admin.team' model.team.id}} Team {{/link-to}}
in a component rendered in the organization.admin template where I pass model=model. But now I get the same error (Assertion Failed: You need to pass a model name to the store's modelFor method) in the Javascript console when rendering the organization.admin template.
If you pass Object to {{#link-to}} helper. It skips the model hook. So you could basically send {{#link-to 'team' organization.team}}Without having to write "model" hook.
"It makes sense and it might save a request to the server but it is, admittedly, not intuitive. An ingenious way around that is to pass in, not the object itself, but its id" - https://www.toptal.com/emberjs/the-8-most-common-ember-js-developer-mistakes".
So you should do
hbs
{{#link-to 'team' organization.team.id}} Link to team management {{/link-to}}
route
model(params) {
return this.store.findRecord('team', params.team_id)
}
you can use modelFor('parent') method to get organization model.
like that
//app/routes/organization/admin/team.js
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
let organization = this.modelFor('parent');
return this.store.findRecord('team', params.team_id)
}
});
i think you wants to do something like that.
basically ember does not support nested routes.
I'm trying to set queryParams in an Ember controller, but they don't seem to be updating the URL at all.
I have this abbreviated mixin being applied to the route:
import Ember from 'ember';
import ControllerPaginationMixin from './controller-pagination';
export default Ember.Mixin.create({
setupController(controller, model) {
this._super(controller, model);
controller.reopen(ControllerPaginationMixin);
}
});
And here's the abbreviated controller mixin that is applied above:
import Ember from 'ember';
export default Ember.Mixin.create({
sortKey: null,
queryParams: ['sortKey'],
actions: {
sort(key) {
this.set('sortKey', key);
}
});
When I call the sort method from a component, I can see in the Ember Inspector that the sortKey property has been changed to the correct new value, but the URL remains unchanged. Am I missing something?
Your problem is that you're trying to customize the controller class at the runtime.
You will reopen the controller every time a user visits the route, that's ridiculous.
Simply extend the controller definition with the mixin and you're good to go.
I have a problem getting the models inside a controller of a route accessed using {{link-to}}
From my understanding (after reading http://emberjs.com/guides/routing/asynchronous-routing/) the model hook of a route doesn't get called when the route is accessed from a {{link-to 'route' model}}. The model is passed directly to the controller. This is a way that Ember ensures that no AJAX called will be made unnecessarily.
For example if I go to {{link-to 'post-review' post}} and I need to pass more than a post model to the PostReviewController.
App.Router.map(function () {
...
this.resource('post-review' , {path: '/post-review/:id'});
...
});
PostReviewRoute = Ember.Route.extend({
//method doesn't get called
model: function(params){
return Em.RSVP.hash({
post: this.store.find('post', params.id),
reviewTypes: this.store.find('reviewType')
});
}
});
The ReviewTypeis a model which has no relationship with Post so that I can access it directly using post.reviewType. A post has several reviews. A review has a reviewType. But I must show all the reviewTypes inside of a combobox.
Anyways, the model hook doesn't get called and I cannot access the this.get('reviewTypes') from PostReviewController. I understand that the beforeModel or afterModel hooks are used for this purpose: to pass additional models to a controller when the route it's accessed from a link-to and not directly from the browser URL. The documentation doesn't show how you can do that! Please enlighten me if you know how!
Thanks!
setupController to the rescue, in your route use the setupController hook to set the reviewTypes like so:
PostReviewRoute = Ember.Route.extend({
setupController: function(controller, model){
var postId = model.get('id');
this._super.apply(this, arguments);
this.store.find('reviewType').then((records)=> {
controller.set('reviewTypes', records);
});
this.store.find('post', postId).then(....)
},
// your code
});
You should now be able to call this.get('reviewTypes').
Let me know if this does it for you.
I am trying to understand the setupController and model hooks, will they be invoked only in case of dynamic segments?
This is my router configuration, I see the application is working fine,but I do not see these hooks getting executed:
// Router, this need to connect view and controller
App.Router.map(function(){
this.resource("login", {path : "/"});
this.resource("home" , {path : "home/:home_id"});
});
App.Router.IndexRoute = Ember.Route.extend({
setupController:function(controller,model){
console.log("in setupController hook for index route");
}
});
App.Router.LoginRoute = Ember.Route.extend({
setupController:function(controller,model){
console.log("in setupController hook for login route");
}
});
App.Router.HomeRoute = Ember.Route.extend({
setupController:function(controller,model){
console.log("in setupController hook for login route");
}
});
Assuming you are using the latest ember (1.0.0-RC.1) You should define your routes like this:
App.HomeRoute = Ember.Route.extend({
...
});
They are part of your App, and don't have the Router part.
Working JSBin example
As a note on model and setupController hook behavior:
In a route, model will only be called when navigating directly to a URL containing a dynamic segment. The parameters passed into model are used to retrieve the model for that route using the dynamic segment.
If the route is reached using a {{#linkTo route myObject}} or transitionTo(myObject) call then the passed object is used to call setupController directly and model is not called.
The setupController hook will be called every time the route enters the
Ember API docs for model
Ember API docs for setupController