As I said before, configureRouter()
doesn’t know about project_id, you have no way to put the project object into settings of every child route.
Here is a resolver we use internally. SingletonFactory
guarantees if you call the factory method with same arguments, you always get the same instance back. So here you can share same projectService
in all your child routes.
If more people find SingletonFactory
useful, I will publish it as an Aurelia plugin.
singleton-factory.js
import {resolver} from 'aurelia-dependency-injection';
const FACTORY_MAP = new Map();
/**
* Used to allow injecting dependencies but also passing data to the constructor.
* if additional data are same, return same instance.
*/
@resolver()
export class SingletonFactory {
/** @internal */
_key;
_map = new Map();
/**
* Creates an instance of the Factory class.
* @param key The key to resolve from the parent container.
*/
constructor(key) {
this._key = key;
}
/**
* Called by the container to pass the dependencies to the constructor.
* @param container The container to invoke the constructor with dependencies and other parameters.
* @return Returns a function that can be invoked to resolve dependencies later, and the rest of the parameters.
*/
get(container) {
return (...rest) => {
let created;
this._map.forEach((value, key) => {
if (created) return;
if (key.length !== rest.length) return;
for (let i = 0, ii = rest.length; i < ii; i += 1) {
if (key[i] !== rest[i]) return;
}
created = value;
});
if (created) {
return created;
} else {
const instance = container.invoke(this._key, rest);
this._map.set(rest, instance);
return instance;
}
};
}
/**
* Creates a Factory Resolver for the supplied key.
* @param key The key to resolve.
* @return Returns an instance of Factory for the key.
*/
static of(key) {
const created = FACTORY_MAP.get(key);
if (created) {
return created;
} else {
const instance = new SingletonFactory(key);
FACTORY_MAP.set(key, instance);
return instance;
}
}
}
project-service.js
uses partial injection, projectId will be provided later.
@inject(HttpClient)
export class ProjectService() {
project = null;
constructor(client, projectId) {
this.client = client
}
reloadProject() {
// something like this
return this.client.fetch(/*...*/)
.then(json => this.project = json.project);
}
reloadOtherProjectRelatedInfo() {}
}
In /projects/:project_id
@inject(SingletonFactory.of(ProjectService))
export class Project {
constructor(getProjectService) {
this.getProjectService = getProjectService;
}
activate(params, routeConfig) {
this.projectId = params.project_id;
this.projectService = this.getProjectService(this.projectId);
return this.projectService.reloadProject();
}
}
In /projects/:project_id/other
@inject(SingletonFactory.of(ProjectService))
export class Other {
constructor(getProjectService) {
this.getProjectService = getProjectService;
}
activate(params, routeConfig) {
this.projectId = params.project_id;
this.projectService = this.getProjectService(this.projectId);
}
@computedFrom('projectService', 'projectService.project')
get project() {
return this.projectService && this.projectService.project;
}
}