I've done
ember g route auth
ember g route auth/pending
Which then gave me :
app/
routes/
auth/
pending.js
auth.js
and my router has
this.route('auth', function() {
this.route('pending', { path: '/pending/:steamid/:token'});
});
Which everything is fine, when I visit
http://localhost:4200/auth/pending/1/2
The page loads, but how do I access :steamid and :token outside of the model.
I'd like to use it so that I can set values in my session service
Like:
import Ember from 'ember';
export default Ember.Route.extend({
session: Ember.inject.service(),
steamID: this.get(// Params Some How),
token: this.get(// Params some How)
thing(params) {
this.get('session').set('tokenID', token),
this.get('session').set('steamID', steamID)
}
});
^^ Pseudo code to express what I'm trying to accomplish.
While it's not in the website documentation, looking at the source code of the Transition object passed to some Route hooks (e.g. afterModel and beforeModel) it have a params property which contains the dynamic segment params.
So you can, for example:
import Ember from 'ember';
export default Ember.Route.extend({
session: Ember.inject.service(),
thing(params) {
// Do some check and returns the result
},
beforeModel (transition) {
if (!this.thing(transition.params)) {
transition.abort();
this.transitionTo('/login');
}
}
});
You can set them in your service from many different hooks:
import Ember from 'ember';
export default Ember.Route.extend({
session: Ember.inject.service(),
/* Access from beforeModel */
beforeModel(transition) {
this.get('session').setProperties({
tokenID: transition.params.token,
steamID: transition.params.steamid
});
},
/* Access from model */
model(params, transition) {
this.get('session').setProperties({
tokenID: params.token,
steamID: params.steamid
});
}
});
If you ask me model hook is the best choice. Especially if you want your query params to refresh the model every time they change (see guide).
Related
currently I'm thinking of the way to load statics into my Ember app.
The problem:
I have app branded logo, app name, app title (browser tab label), texts for routes etc.
What I'm doing now is the following:
model() {
let defaultHeaderModel = {
logo: '/img/logo-cloud.svg',
brand: {
name: 'CloudCenter',
logo: '/img/logo-cloud.svg'
},
userLinks: [{
text: 'Logout',
route: 'logout'
}],
navigation: [{
text: 'Login',
route: 'login'
}]
};
}
As you can see all of the values are hardcoded. What I'd like to do is to somehow load that "statics" and use them through some variables. For ex: header.logo = resources.logo.
My thoughts:
1) Use environment - store all of that values in the config.js and import it where needed. Cons: not sure if that data belongs to environment
2) ES6 POJO which can be imported to the app.
3) .json and some staticsService which will load .json file and through it I will have access to that values.
Are there any standardized approach to do such things? Or maybe better suggestions?
You can create service, and have method(loadData) which will return Promise and will be resolved with your JSON data and update property in service. You need to call loadData in beforeModel hook, after the all the promises resolved only then it will move to model hook.
Refer twiddle basic demonstration
services/my-service.js
import Ember from 'ember';
export default Ember.Service.extend({
defaultHeaderModel:{},
loadData(){
var myServiceDataLoadPromise = Ember.RSVP.Promise.resolve({one:1});
myServiceDataLoadPromise.then(result =>{
this.set('defaultHeaderModel',result);
});
return myServiceDataLoadPromise;
}
});
routes/application.js
inside beforeModel hook, you can load service with data, it can be done any of the route which requires data.
import Ember from 'ember';
export default Ember.Route.extend({
myService: Ember.inject.service(),
beforeModel()
{
return Ember.RSVP.all([this.get('myService').loadData()]);
}
});
controllers/application.js
import Ember from 'ember';
export default Ember.Controller.extend({
myService: Ember.inject.service(),
appName: 'Ember Twiddle'
});
templates/application.hbs
{{myService.defaultHeaderModel.one}}
I have a project where I need to build an Ember application. The application will have many routes and some of the routes will have some model.
My problem at the moment is that some information is global, meaning they are present in each page (.hbs) and I need to update it periodically.
I've tried to put information on the application route like the following but it didn't work, the content is not accessible on other routes:
import Ember from 'ember';
export default Ember.Route.extend({
model: function(params) {
return Ember.$.getJSON('/api/users/current')
}
});
I've also tried to reload the information with a setInterval but this didn't work either.
import Ember from 'ember';
export default Ember.Route.extend({
init: function() {
var thyself = this;
var interval = setInterval(function(){
thyself.my_reload()
}, 1000);
this.set('interval', interval);
this.set('counter', {});
},
my_reload: function() {
var counter = this.get('counter');
if (counter >= 10) {
clearInterval(this.get('interval'));
}
this.set('data', Ember.$.getJSON('/api/users/current'));
}
});
Where can I place this information so it will be available on all routes? And how can I reload the information periodically?
I'm using ember-cli
#NicosKaralis,
you should use service for it.
You can generate it by command: ember generate service name-of-service
And there you should create methods.
When you want to get access from your controller you should inject it in your controller:
nameOfService: Ember.inject.service(), (remember camelCase here)
and if you want some method from your service in your controller you will use it like this (example with computed property, you can also use it without computed property):
someComputedFunctionInController: Ember.computed(function() {
this.get('nameOfService').yourFunctionFromService();
},
nextComputedFunctionInController: Ember.computed(function() {
this.get('nameOfService.getSomethingFromService');
}
for more:
https://guides.emberjs.com/v2.7.0/tutorial/service/
Hope, it will help you.
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 do something like this in my routes:
this.route('products', { path: "/products/*choises"}, function() {
this.route('promotion', {path: "/promotion/*offers"});
});
product route:
offerPath: function(params){
this.transitionTo('product.promotion', params);
}
The problem is that it doesn't matter the promotion that I visit, the app thinks is part of the products route.
How can I do this? I need them to be nested.
Update:
You can use beforeModel(transition) hook in router to check what's in the url.
http://example.com/products/manufacturer-209/series-881/tag-17143/none/494822/flawless
import Ember from 'ember';
export default Ember.Route.extend({
beforeModel(transition) {
console.log(transition.params.products.choises)
// if you use this url: http://example.com/products/manufacturer-209/series-881/tag-17143/none/494822/flawless
// console log would be: "manufacturer-209/series-881/tag-17143/none/494822/flawless"
}
});
At least you have the rest of the url so, you can filter out the important information and redirect with this.transitionTo() to the exact place.
You could have the following route:
http://example.com/products/123/promotions/456
or
http://example.com/products/awesome_souce/promotions/monday_deal
In the first case, your route would look like this:
this.route('product', { path: "/products/:product_id"}, function() {
this.route('promotion', {path: "/promotions/:promotion_id"});
});
In the second case, maybe like this:
this.route('product', { path: "/products/:product_name"}, function() {
this.route('promotion', {path: "/promotions/:promotion_name"});
});
Finally, your route handlers can download the proper models (example for the first case):
// app/routes/product.js
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
return this.store.findRecord('product', params.product_id);
}
});
---
// app/routes/product/promotion.js
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
// you can get access to the parent route model if you need for the api query
const product = this.modelFor('product');
return this.store.findRecord('promotion', params.promotion_id);
}
});
If you need only the param from the product route, instead of returning a whole record, for example you can just return params.product_name, so you will have access to a string with this.modelFor('product') in a subroute level.
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.