I'm using ember 2.12
Here's my route
import Ember from 'ember';
export default Ember.Route.extend({
rentalService: Ember.inject.service('rentals-service'),
model(){
this.get('rentalService').findRentals();
console.log('Inside route');
console.log(this.get('store'));
return this.get('store').findAll('rental');
}
});
Here's my ember rental-service
import Ember from 'ember';
export default Ember.Service.extend({
findRentals() {
console.log("Inside servce");
console.log(this.get('store'));
return "hello from servce";
}
});
Why is it I cannot access the ember-data on the rental-service? whenever I console .log this.get('store') inside the rental-service it returns an undefined. However on the routes, whenever I console.log the same code it returns this value.
Does this mean I cannot perform a rest call using ember data inside a service?
I'm using Mirage to mock a web-server/http requests
You cannot access the store inside an ember component/service. A workaround for this is to retrieve the store via dependency injection.
export default Ember.Service.extend({
store: Ember.inject.service('store'),
findRentals() {
console.log("Inside service");
console.log(this.get('store'));
return "hello from service";
}
});
Be wary if you have another service with a name of store, it might fetch that one.
Related
I have a controller in my ember 2.18 app and I want to make it listen to some event myEventName triggered somewhere in the app, to change the model properties.
According to the API docs for this version the way to catch an emitted event is like this:
import Evented from '#ember/object/evented';
import Controller from '#ember/controller';
// extend some object, like a Controller
const myExtendedObject = Controller.extend(Evented, {
// stuff ...
});
myExtendedObject.on('myEventName', function (args) {
console.log("catch importDone ok", args);
});
export default myExtendedObject;
the code compiles well with ember build dev,
but in the browser's JS console I get this error message:
Error: Assertion Failed: on called without valid event names error.js:40
I tried renaming event, but I cannot find why the event name is wrong.
I also tried to set three arguments to the on method, but it is still bugging with the event name.
What am I missing?
Edit:
I made an Ember twiddle showing that events are scoped to components.
I would like to catch them from anywhere;
like triggering an event from a Service and catch it in a Route.
https://ember-twiddle.com/ce22cc0a542e8e0997a1ad57a4a9688c?fullScreen=true
You can use it like this:
import { on } from '#ember/object/evented';
export default Controller.extend(Evented, {
init() {
this._super(...arguments);
this.trigger('greet');
},
myGreetImplementation: on('greet', function() {
console.log('hello');
})
});
Another example: Using a service to manage the user settings and subscribing to changes:
export default Service.extend(Evented, {
...
changeProfilePicture() {
...
this.trigger('profilePictureChanged', ... event parameters ...);
}
});
Then you could watch for such event anywhere using the on method:
export default Controller.extend({
userSettings: service(),
init() {
this._super(...arguments);
this.get('userSettings').on('profilePictureChanged', this, this.profilePictureChanged);
},
profilePictureChanged(... event parameters ...) {
...
}
});
There error you get is coming from here:
https://github.com/emberjs/ember.js/blob/6fc89cdf13124d88b8ae6adf99bb02a8c0cdf508/packages/ember-metal/lib/events.ts#L211
(You can just paste error messages in the github search or use the debugger to find out more about why something is failing)
Update: Extending your twiddle to have the Controller register on the service's event:
import Ember from 'ember';
import { inject as service } from '#ember/service';
import { on } from '#ember/object/evented';
export default Ember.Controller.extend({
appName: 'Ember Twiddle',
myService: service(),
init() {
this._super(...arguments);
this.get('myService').on('mycall', this, this.mycallHandler);
},
mycallHandler: on('mycall', function() {
console.log('here we are');
})
});
I have a controller A that sent an action with this.send('makeItHappen'), and I want to handle it in controller B. How do I do it?
JS:
// controllers/documents/datasets/controller-A
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
sendToDataCenter() {
this.send('makeItHappen'); // this throws an error
}
}
});
// controllers/controller-B
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
makeItHappen() {
console.log('It works!!');
}
}
});
In Controller B, it throws an error:
Uncaught Error: Nothing handled the action 'makeItHappen'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble.
Please, can anyone help? Thank you.
In general, each route will have one default controller if it's not defined.
In controller-A, this line of code this.send('makeItHappen'); will look for the makeItHappen method in actions hash of the datasheets,documents, application controller and its corresponding route if makeItHappen is defined anywhere then won't get this error.
To implement what you need,
Currently, in your route/controller hierarchy, there is no parent-child relationship between controller-A and controller-B. so you can just inject controller-B inside controller-A and call makeItHappen directly.
// controllers/documents/datasets/controller-A
import Ember from 'ember';
export default Ember.Controller.extend({
controllerB:Ember.inject.controller('controller-B');//this should be already instantiated ie,this corresponding route should be visited earlier otherwise you will get `unknown injection: controller:users' Error
actions: {
sendToDataCenter() {
this.get('controllerB').send('makeItHappen');
}
}
});
How to get user object in abilities source file in Ember-can addon.
This is how my abilities file looks like.
import Ember from 'ember';
import { Ability } from 'ember-can';
export default Ability.extend({
canWrite: Ember.computed('user.isAdmin', function() {
return this.get('user.isAdmin');
})
});
According to the official documentation:
Injecting the user
How does the ability know who's logged in? This depends on how you implement it in your app!
If you're using an Ember.Service as your session, you can just inject it into the ability:
// app/abilities/foo.js
import Ember from 'ember';
import { Ability } from 'ember-can';
export default Ability.extend({
session: Ember.inject.service()
});
If you're using ember-simple-auth, you'll probably want to inject the simple-auth-session:main session into the ability classes.
To do this, add an initializer like so:
// app/initializers/inject-session-into-abilities.js
export default {
name: 'inject-session-into-abilities',
initialize(app) {
app.inject('ability', 'session', 'simple-auth-session:main');
}
};
The ability classes will now have access to session which can then be used to check if the user is logged in etc...
I have a popup component in which i have a button and on click of that if im in my target route (mainRoute) i just want to pass the query parameters to my current route, but if i'm in another route i just want to transit with new query parameters. I know neither transitionTo or transitionToroute work. Is there any way to do that?
The transitionTo wouldn't work because you don't have access to routing from inside your component context. You can add the routing support at any place in your app using -routing service like so:
export default Ember.Component.extend({
routing: Ember.inject.service('-routing'),
someFuncUsingRouting(){
let routing = this.get('routing');
routing.transitionTo('some-route');
}
});
This is my code for logout function that close the session and redirect you to /login route.
import Ember from 'ember';
export default Ember.Component.extend({
authManager: Ember.inject.service('session'),
routing: Ember.inject.service('route'),
tagName: '',
actions: {
invalidateSession() {
console.log("logout invalidateSession");
this.get('authManager').invalidate();
let routing = this.get('routing');
routing.transitionTo('login');
}
}
});
This is working code for:
ember-cli: 2.8.0
node: 7.1.0
I have a form that transitions through several views. Currently each controller.js file has a long list of these Ember.computed.alias. How can I break that out into one file and import it into each controller?
Currently in each controller.js
entityEmail: Ember.computed.alias('controllers.checkout.entityEmail'),
entityDOB: Ember.computed.alias('controllers.checkout.entityDOB'),
entityPhone: Ember.computed.alias('controllers.checkout.entityPhone'),
entityAddress1: Ember.computed.alias('controllers.checkout.entityAddress1'),
entityAddress2: Ember.computed.alias('controllers.checkout.entityAddress2'),
entityCity: Ember.computed.alias('controllers.checkout.entityCity'),
I would like to pull all that out into a file so I can simply import some 1 liner in each controller.js
This is a classic use-case for Ember.Mixin.
You can extract all these computed props into a single mixin and extend every controller (that needs to have these props) with it.
Add the following mixin to your app
// app/mixins/entity-form.js
import Ember from 'ember';
const { Mixin, inject, computed: { alias } } = Ember;
export default Mixin.create({
checkout: inject.controller(),
entityEmail: alias('checkout.entityEmail'),
entityDOB: alias('checkout.entityDOB'),
entityPhone: alias('checkout.entityPhone'),
entityAddress1: alias('checkout.entityAddress1'),
entityAddress2: alias('checkout.entityAddress2'),
entityCity: alias('checkout.entityCity')
});
And then use it in a controller
// app/controllers/example.js
import EntityFormMixin from 'yourAppName/mixins/entity-form';
const { Controller } = Ember;
export default Controller.extend(EntityFormMixin, {
// rest of controller's props and functions
});
Note: Ember.inject API is available since Ember 1.10.0. In case you are using an older version you need to replace the inject line with: needs: ['checkout'] and prefix the aliases with "controllers." like you did in your example.