My app has a lot of reports, and I have dateBegin and dateEnd in all of then.
The desired behaviour is:
app first load, dateBegin = month begin (jun-01) / dateEnd = today (jun-11)
when user change dates (let's say to mai-01 / mai-31), all controllers get the new dates
The code that I have now:
// app/services/defaults.js
import Ember from 'ember';
export default Ember.Service.extend({
init: function () {
this._super();
var dateEnd = moment().format('YYYY-MM-DD');
var dateBegin = moment().startOf('month').format('YYYY-MM-DD'));
if (!this.get('dateEnd')) { this.set('dateEnd', dateEnd); }
if (!this.get('dateBegin')) { this.set('dateBegin', dateBegin }
}
});
// app/components/select-dates-in-reports.js
import Ember from 'ember';
export default Ember.Component.extend({
defaults: Ember.inject.service(),
displayDateBegin: null,
displayDateEnd: null,
dateBegin: Ember.computed.alias('defaults.dateBegin'),
dateEnd: Ember.computed.alias('defaults.dateEnd'),
setInitialParams: Ember.on('init', function () {
this.set('displayDateBegin', this.get('dateBegin'));
this.set('displayDateEnd', this.get('dateEnd'));
}),
actions: {
chooseParams: function () {
this.set('dateBegin', this.get('displayDateBegin'));
this.set('dateEnd', this.get('displayDateEnd'));
}
}
});
// app/mixins/query-params-for-reports.js
import Ember from 'ember';
export default Ember.Mixin.create({
queryParams: ['dateBegin', 'dateEnd'],
defaults: Ember.inject.service(),
dateBegin: Ember.computed.alias('defaults.dateBegin'),
dateEnd: Ember.computed.alias('defaults.dateEnd')
});
// app/mixins/routes-query-params-for-reports.js
import Ember from 'ember';
export default Ember.Mixin.create({
queryParams: {
dateBegin: {
refreshModel: true
},
dateEnd: {
refreshModel: true
}
},
model: function(params) {
return this.store.find(this.get('modelName'),
{
dateBegin: params.dateBegin,
dateEnd: params.dateEnd
}
);
}
});
It works as desired just after each controller is initialized:
user enter the app, and visit controller1. dateBegin = jun-01 / dateEnd = jun-11
on the same controller1, user change dates to dateBegin = mai-01 / dateEnd = mai-31
user visit controller2. Here is the Problem. The dates are set to dateBegin = jun-01 / dateEnd = jun-11
on the same controller2, user change dates to dateBegin = apr-01 / dateEnd = apr-30
user visit controller1 again. Now it works. The dates are set to dateBegin = apr-01 / dateEnd = apr-30
I tried all I could find over the net.
Create Initializers, used localStorage, etc. Nothing works.
Can anyone helps me??
thanks!
Ember Dependency Injection to the rescue!
You can create a singleton object to hold the dates:
App.SelectedDates = Ember.Object.extend({
dateBegin: null,
dateEnd: null // or whatever value you want...
});
Then, inject that object into ALL controllers like this:
Ember.Application.initializer({
name: 'register-global-dates',
initialize: function(container,app) {
app.register('my:globalDate', App.SelectedDates.create(), {
singleton: true,
instantiate: false
});
app.inject('controller', 'dateglobal', 'my:globalDate');
}
});
Now, in your controller(s), you can do this:
this.dateglobal.set('dateBegin', '2015/01/12');
It's the same object in all controllers.
I hope I am understanding your problem correctly and that this is the solution...
Related
I have been trying to implement pagination (I've tried both ember-cli-pagination and ember-simple-pagination) for my application but I've had a lot of issues. So I decided to try custom pagination and noticed that I cannot pass parameters into my query. For instance, when visiting my api at: http://jsonplaceholder.typicode.com/posts?_start=0&_limit=10, start and limit both work properly. When calling it in my route, it seems to ignore that entirely and just give me all entries. I would appreciate all insight into what I am doing wrong or how to properly implement pagination in this case.
app/adapters/post.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
host:'https://jsonplaceholder.typicode.com',
pathForType(){
return 'posts';
}
});
app/models/post.js
import DS from 'ember-data';
const { Model } = DS;
export default Model.extend({
user:DS.belongsTo('user'),
title:DS.attr('string'),
body:DS.attr('string'),
});
app/routes/post.js
import Route from '#ember/routing/route';
import { set } from '#ember/object';
import { hash } from 'rsvp';
export default Route.extend({
model() {
return hash({
post: this.store.query('post', {
start: 0,
limit: 10
}),
user: this.store.findAll('user')
});
},
setupController(controller, model) {
this._super(...arguments);
set(controller, 'posts', model.post);
set(controller, 'users', model.user);
}
});
You need define the query params in both side Route and Controller.
app/routes/post.js
import Route from '#ember/routing/route';
import { set } from '#ember/object';
import { hash } from 'rsvp';
export default Route.extend({
queryParams = {
start: {
refreshModel: true
},
limit: {
refreshModel: true
}
},
model() {
return hash({
post: this.store.query('post', {
start: 0,
limit: 10
}),
user: this.store.findAll('user')
});
},
setupController(controller, model) {
this._super(...arguments);
set(controller, 'posts', model.post);
set(controller, 'users', model.user);
}
});
And inside app/controllers/post.js
import Controller from '#ember/controller';
export default class ArticlesController extends Controller {
queryParams = ['start', 'limit'];
start = 1;
limit = 5;
}
Ember by default does not call model when query params are changed. We tell it to do so any time start/limit changes, through refreshModel: true.
This is a crappy example, but I am merely trying to use a mixin's property in a controller. I did the same thing in a route and could access that property. I've tried every way to reference a property I know... What am I misunderstanding?
// app/mixins/author-data.js
import Ember from 'ember';
export default Ember.Mixin.create({
authorName: 'Example author name',
});
// app/controllers/application.js
import Ember from 'ember';
import AuthorDatas from 'app-name/mixins/author-data';
export default Ember.Controller.extend(AuthorDatas, {
siteTitle: `Site title`,
fromAuthorData: this.get('authorName'),
// returns 💩 - what is the proper syntax?
actions: {
showAuthor() {
var author = this.get('fromAuthorData');
console.log(`Author from controller: ${author}`);
},
},
});
// app/templates/application.hbs
{{fromAuthorData}}
This works...
// app/routes/application.js
import Ember from 'ember';
import AuthorDatas from 'app-name/mixins/author-data';
export default Ember.Route.extend(AuthorDatas, {
afterModel() { // arbitrary
var intro = `Author from route:`;
console.log(`${intro} this.authorName`, this.authorName );
console.log(`${intro} this.get('author-name')`, this.get('authorName') );
},
});
(I would have made an ember-twiddle - but I wasn't sure if Mixins would work the same way ~ since they aren't on the list and there is 0 documentation)
The fromAuthorData property on your controller should be defined like this (I think):
fromAuthorData: Ember.computed('authorName', function() {
return this.get('authorName'); // or whatever derived value you need
}
To understand the problem we need to talk about scope, when you extend/create an object you are merely passing in options, your code is no different than:
let options = {
siteTitle: `Site title`,
// `this` is undefined since we are in strict mode
fromAuthorData: this.get('authorName'),
actions: {
showAuthor() {
var author = this.get('fromAuthorData');
console.log(`Author from controller: ${author}`);
},
}
};
export default Ember.Controller.extend(AuthorDatas, options);
Now to access properties that rely on this being the object holding it you will need a function that is run with the object as it's context that returns that value, enter computed properties.
Your code becomes:
// app/controllers/application.js
import Ember from 'ember';
import AuthorDatas from 'app-name/mixins/author-data';
const { computed } = Ember;
export default Ember.Controller.extend(AuthorDatas, {
siteTitle: `Site title`,
// We add `authorName` as the dependent key, should it change `fromAuthorData` will update
fromAuthorData: computed('authorName', function() {
// your author data stuff
let authorName = this.get('authorName');
// ...
return authorDetails;
}),
actions: {
showAuthor() {
var author = this.get('fromAuthorData');
console.log(`Author from controller: ${author}`);
},
},
});
I got a "get-text" helper which translate my static fields depending on a config variable : ENV.LOCALE.
The thing is, I'd like to recompute my if my ENV.LOCALE gets modified. I tried several things from sending events to Ember.observer, without much success.
// controllers/application.js
locale: function() {
var locale = this.get('isFrench') === true ? 'fr' : 'en';
ENV.LOCALE = locale;
return locale;
}.property('isFrench'),
//helpers/get-text.js
import Ember from 'ember';
import ENV from '../config/environment';
export default Ember.Helper ( function(key, locale) {
var lang = {
save: {
'fr': 'Enregistrer',
'en': 'Save',
},
}
return new Ember.Handlebars.SafeString(lang[key][ENV.LOCALE]);
});
Bottom line, how can I recompute my helper when a global property changes?
After digging threw the documentation, I found this chapter about dependency injection. This combined with the API documentation on Ember.Helper I came up with the following solution :
1st I created a service "locale-manager"
// services/locale-manager.js
import Ember from 'ember';
export default Ember.Service.extend({
isFrench: true,
locale: function() {
var locale = this.get('isFrench') === true ? 'fr' : 'en';
return locale;
}.property('isFrench'),
});
Then I inject my service into my helper and recompute it everytime time the property of locale is changed.
// helpers/get-text.js
import Ember from 'ember';
export default Ember.Helper.extend({
localeManager: Ember.inject.service(),
onLocaleChange: Ember.observer('localeManager.locale', function() {
this.recompute();
}),
compute(params) {
var key = params[0];
var lang = {
enregistrer: {
'fr': 'Enregistrer',
'en': 'Save',
},
var locale = this.get('localeManager.locale');
return new Ember.Handlebars.SafeString(lang[key][locale]);
}
});
I am trying to create and save a model in Ember but only the first entry in my form is saving leaving the others blank.
Before saving all of the models attributes are correct. (shown with logs)
Any help greatly appreciated!
My Model is:
import DS from 'ember-data';
export default DS.Model.extend({
endpoint: DS.attr('string'),
playerVersion: DS.attr('string'),
createdAt: DS.attr('date'),
updatedAt: DS.attr('date')
});
My Route is:
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.createRecord('account');
}
});
My Controller is:
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
save: function() {
var _this = this;
var model = this.get('model');
console.log(model.get('endpoint')); //Shows correct endpoint
console.log(model.get('playerVersion')); //Shows correct playerVersion
model.save().then(function(account) {
console.log(model.get('endpoint')); //Shows correct endpoint
console.log(model.get('playerVersion')); //Shows nothing
_this.transitionToRoute('accounts.index');
});
return false;
}
}
});
UPDATE - Was some settings needed on the custom Serializer needed.
export default JsonApiSerializer.extend({
keyForAttribute: function(key) {
//return Ember.String.dasherize(key);
return Ember.String.camelize(key);
},
keyForRelationship: function(key) {
//return Ember.String.dasherize(key);
return Ember.String.camelize(key);
},
keyForSnapshot: function(snapshot) {
//return Ember.String.dasherize(snapshot.typeKey);
return Ember.String.camelize(snapshot.typeKey);
},
});
I have a cruise model which hasMany trips. A trip stores the start and end date. I'd like to filter cruises which start at or later than earliestStartDate and which end latests at latestEndDate.
app/models/cruise.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
trips: DS.hasMany('trip', { async: true })
});
app/models/trip.js
import DS from 'ember-data';
export default DS.Model.extend({
starts_on: DS.attr('date'),
ends_on: DS.attr('date')
});
app/templates/index.hbs
{{date-picker date=earliestStartDate valueFormat='YYYY-MM-DD'}
{{date-picker date=latestEndDate valueFormat='YYYY-MM-DD'}}
How can I change filteredCruises in this controller to filter the cruises which have trips within the given dates?
app/controllers/index.js
[...]
filteredCruises: function() {
var earliestStartDate = this.get('earliestStartDate');
var latestEndDate = this.get('latestEndDate');
var cruises = this.get('model.cruises');
return cruises;
}.property('model.cruises','earliestStartDate','latestEndDate'),
[...]
I haven't touched Ember in a while, and I haven't tested/executed this code, but I think this might work for you (and I am sure this can be optimized):
[...]
filteredCruises: function() {
var earliestStartDate = this.get('earliestStartDate');
var latestEndDate = this.get('latestEndDate');
var cruises = this.get('model.cruises');
return cruises.filter(function(cruise) {
return cruise.get('trips').filter(function(trip) {
return ((trip.get('starts_on') >= earliestStartDate) && (trip.get('ends_on') <= latestEndDate));
});
});
}.property('model.cruises','earliestStartDate','latestEndDate'),
[...]