@smoovy/composer
v1.0.13
Published
Component Manager, Service Manager all in one
Downloads
70
Maintainers
Readme
@smoovy/composer
Very simple component/service system. Optimized for TypesScript usage.
Installation
yarn add @smoovy/composer
or
npm install --save @smoovy/composer
Component
A component is a very simple class, you just tell the composer what selector to use and it'll manage all updates and detects if the element is still in the DOM etc.
import { component } from '@smoovy/composer';
/** Elements with the attribute `data-test` will be selected */
@component('test')
class TestComponent {
constructor(
private element: HTMLelement
) {}
/** On creation after the injectors are done */
onCreate() {}
/** After the element is no longer in the DOM */
onDestroy() {}
/** Helper method to make unlistening easier **/
onListen() {
return () => {
console.log('unlisten from listeners');
};
}
}
// you can change specify a different selector like this
@component({
selector: '.select-this-class'
})
Lifecycle methods are:
onCreate
,onListen
andonDestroy
. All are optional ´
Component config
You can inject config from the element dataset into your component like this:
<div
data-test-message="Hello Universe!"
data-test-count="8"
></div>
<!-- It's also possible to define an object. So the following is the same: -->
<div
data-test='{ "message": "Hello Universe!", "count": 8 }'
></div>
If you define both the "non-json" value has priority
import { component, config } from '@smoovy/composer';
@component('test')
class TestComponent {
@config('message')
private message: string;
@config('count', {
type: Number,
parse: (val: number) => val * val
})
private count = 0;
onCreate() {
console.log(this.message); // "Hello Universe!"
console.log(this.count); // 64
}
}
Component query
To simplify the step of querying elements from your root element, you can use
the query
or queryAll
injector like this:
import { component, query, queryAll } from '@smoovy/composer';
@component('test')
class TestComponent {
@query('.headline')
private headline: HTMLElement;
@queryAll('p', { parse: list => Array.from(list) })
private paragraphs: HTMLElement[] = [];
onCreate() {
console.log(this.headline); // contains DOM element
console.log(this.paragraphs); // contains array of DOM p elements
}
}
Service
A service is a class that exists as a singleton inside your project.
This "singleton functionality" is achieved by using injectors. So you
can inject services inside components
and other services
. A service
is basically a Promise
with extra functionality.
import { Service } from '@smoovy/composer';
class TestService extends Service<any, TestService> {
get name() {
return 'test';
}
get child() {
return TestService;
}
async init() {
this.resolve(this.config.msg);
}
}
Creating sub services
A service can have children, so you can split the service into smaller ones
and give them a separate context. For example you have a ScrollerService
.
Now you have a sidescroller which uses a different scroller, you could
create a sub service with a name and different configuration. This allows you
to create reusable components easier. Here's an example
const testService = new TestService({ msg: "I'm the parent" });
testService.addChild('sub1', { msg: "I'm the child" });
// now inside your components you can for the children
let message = '';
if (testService.hasChild('sub1')) {
const sub1 = testService.getChild('sub1');
message = await sub1;
} else {
message = await testService;
}
// message will be "I'm the child"
console.log(message);
Using a service
Services can be injected into components or other services like this:
import { service, component } from '@smoovy/composer';
class TestService2 {
@service(TestService)
private testService: TestService;
async init() {
// make sure to check if it's been activated otherwise it would wait forever
if (this.testService.activated) {
await this.testService;
}
}
}
@component('[data-test]')
class TestComponent {
@service(TestService, true /** await automatically **/)
private message: string;
onCreate() {
// We'll get value immediately since we told
// to await the service on injection
console.log(this.message);
}
}
Composer
The composer glues components and services together. It manages injections, configurations and "garbage collection". Composers are defined with a class like this:
import { composer } from '@smoovy/composer';
@composer({
services: [],
components: []
})
class App {
@composer()
private composer!: Composer;
onCreate() {
console.log(this.composer);
}
}
// Create the app to kick off initialization
new App();
Using composer in components
You can inject the composer into child components and services like this:
import { component, composer } from '@smoovy/composer';
@component('[data-test]')
class TestComponent {
@composer()
private composer: Composer;
onCreate() {
this.composer.update();
}
}
This also works for services
License
See the LICENSE file for license rights and limitations (MIT).