mithril-di v0.1.0
Mithril DI
This library implements a dependency injection mechanism for mithril js.
How to
es6 import
import { DI } from 'mithril-di'commonjs import
const { DI } = require('mithril-di')Basics
Use the DI function to wrap your component definition whenever a component should provide or inject data.
To make a component a provider of something, pass a providers array as part of the options argument (1st argument).
The providers syntax is the same as
const Parent = DI(
// DI options
{
providers: [{ provide: 'greetings', useValue: 'Hello World' }],
},
// component definition
() => {
return {
view: () => m(Child),
}
},
)A component that is wrapped by the DI function will be given an additional injector attribute which then can be used to access provided data.
Closure Components
The injector attribute can be consumed in all lifecycle methods.
However, for closure components one would most likely inject at the beginning of closure.
const Child = DI(({ attrs }) => {
const text = attrs.injector.get('greetings')
return {
view: () => text, // -> Hello World
}
})POJO Components
POJO components dont have a constructor, so the next best place to use the injector would be the oninit lifecycle method
const Child = DI({
oninit: ({ attrs, state }) => {
state.text = attrs.injector.get('greetings')
},
view: ({ state }) => {
return state.text
},
})Class Components
Class components may also be wrapped with the DI function. It looks a bit strange, but the DI behavior is consistent with the previous examples: injector is available in all lifecycle methods as well as in the constructor
const Child = DI(
class {
text: string
constructor(n) {
this.text = n.attrs.injector.get('greetings')
}
view() {
return text
}
},
)Class Components (decorators)
The DI function also acts as a class decorator. Together with the Inject decorator this results in a cleaner syntax.
The main draw back is that the injection happens right before the view method. You can not use the injected data inside oninit but only inside view and oncreate.
import { DI, Inject } from 'mithril-di'
@DI()
class Child {
@Inject('greetings')
private text
oninit() {
console.log(this.text) // -> undefined
}
oncreate() {
console.log(this.text) // -> "Hello World"
}
view() {
console.log(this.text) // -> "Hello World"
return this.text
}
}Providers
class provider
class MyService {
constructor(injector: Injector) {}
}
DI(
{
providers: [
{
provide: MyService,
},
],
},
(injector) => {
injector.get(MyService)
return {
view: () => null,
}
},
)ClassProvider
class MyService {
//
}
class AnotherService {
constructor(injector: Injector) {}
}
DI(
{
providers: [
{
provide: MyService,
useClass: AnotherService,
},
],
},
(injector) => {
injector.get(MyService) // -> instance of AnotherService
return {
view: () => null,
}
},
)value provider
class MyService {
//
}
DI(
{
providers: [
{
provide: MyService,
useValue: new MyService(),
},
],
},
(injector) => {
injector.get(MyService) //
return {
view: () => null,
}
},
)provider factory
class MyService {
//
}
DI(
{
providers: [
{
provide: MyService,
useFactory: (injector) => new MyService(injector),
},
],
},
(injector) => {
injector.get(MyService) //
return {
view: () => null,
}
},
)provider aliasing
class MyService1 {}
class MyService2 {}
DI(
{
providers: [
{ provide: MyService1 },
{
provide: MyService2,
useExisting: MyService1,
},
],
},
(injector) => {
injector.get(MyService2) // -> instance of MyService1
return {
view: () => null,
}
},
)4 years ago