Injecting Services¶
We made use of the implemented LinkTo components to make the menu items link to another route.
Within register-user.js
we encountered a way to make use of both the store
and the router
from within a component class.
In Ember, there are objects, that are accessible form different parts of your app.
These parts are called services
.
Services live for the duration of the app and are used to share state between components and routes, or use persistent connections.
They are also used for user/session authentication, WebSockets, server-sent events or notifications, logging, third-party APIs, or even geolocation.
You can either create your own services or make use of the existing ones, like we did with store
and router
.
To access a service, you need to import { inject } from '@ember/service';
.
Ember provides injectors for a number of different types of objects, thus it is generally good practice to use the as
structure to re-label the injector function to the type of thing we want to inject.
Then, you can either call the service without arguments or pass the registered name of the service.
We did the former.
For Ember, there is no difference between @service router;
or @service('router') router;
, but the second way enables you to rename the service.
The store
service allows us to interact with our backend, while the router
service enables us to use routing from components.
The core idea behind router injection is to have minimal default linkage between different code elements in the framework and instead provide a route through which the developer can explicitly inject the functionality from one code element into another code element.
The injector functions are “smart”, in that if you do not provide a name indicating what service you wish to inject, it will look at the name of the parameter the injected functionality will be assigned to and use that as the name indicating what to inject.
Here, by naming the key “router”, Ember knows to inject the router component.
We can use this service to update the login-page.js
to this
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { inject as service } from '@ember/service';
/**
* Provides backend functionality for Login Page Component used by Login Route
*/
export default class LoginPageComponent extends Component {
/**
* Required variables
* The router service is used to transition to the Modules Route when email
* and password are correct.
* The untracked variables help update the UI.
*/
@service router;
@tracked email = '';
@tracked password = '';
@tracked loginInvalid = false;
classLabel = 'text-danger';
classInput = 'is-invalid';
classSpan = 'invalid-feedback';
/**
* Handles the user submitting the login form.
* Suppresses standard behavior.
* Tests email/password and updates the UI.
*/
@action
login(event) {
event.preventDefault();
if (this.email === 'test@example.com' && this.password === 'password') {
this.loginInvalid = false;
this.router.transitionTo('modules');
} else {
this.loginInvalid = true;
}
}
/**
* Handles the user typing in the email/password input fields.
* Resets the ''loginInvalid'' property to improve usability.
*/
@action
typing() {
this.loginInvalid = false;
}
}
When we log in now, we will be sent directly to the modules list.