Skip to main content
Version: 0.1.x

Lifecycle

SALVO-TS components are Web Components, which means that they're associated with custom HTML elements (like <my-component>). When these elements are used on a page, the browser automatically creates the associated javascript class.

SALVO-TS automatically handles the core Web Component lifecycle and registering your components with the browser.

Below you can see a diagram of the full component lifecycle:

Lifecycle hooks

You can add methods to your components to hook in at various stages during the lifecycle:

typescript
@Component
class MyComponent extends ThemeComponent {
// Runs when the component's element is added to the page
init() {
// Perform your setup - register event listeners, etc.
}
// Runs when the component's element is removed from the page
destroy() {
// Clean up any event listeners you've created and reverse any side-effects.
}
}
typescript
@Component
class MyComponent extends ThemeComponent {
// Runs when the component's element is added to the page
init() {
// Perform your setup - register event listeners, etc.
}
// Runs when the component's element is removed from the page
destroy() {
// Clean up any event listeners you've created and reverse any side-effects.
}
}
Components can be init'd mutiple times

A component is init() every time it's added to a page. If a component is moved in javascript, it'll be destroy() and then init() again in the new location.

Ensure that your component correctly cleans up any side effects (i.e. event listeners) each time it's destroyed.

Example

Here's an example of a well-behaving component:

typescript
@Component
class GreeterComponent extends BaseComponent {
@Prop({required: false}) name?: string;
@Prop({required: false}) dateOfBirth?: string;
@Ref messageSpan: HTMLElement;
popupComponent: null|PopupComponent = null;
init() {
this.messageSpan.textContent = `Hey, ${this.name || 'customer'}!`;
// Register event handlers
this.customer.change.subscribe(this.handleCustomerChanged);
// Create elements
this.popupComponent = document.createElement('popup-component');
document.body.appendChild(this.popupComponent);
this.checkBirthday();
}
destroy() {
// Unregister event handlers
this.customer.change.unsubscribe(this.handleCustomerChanged);
// Clean up elements
this.popupComponent.remove();
}
handleCustomerChanged(customer: null|Customer) {
this.name = customer?.name;
this.dateOfBirth = customer?.getDateOfBirth();
this.checkBirthday();
}
checkBirthday() {
if (!this.dateOfBirth || !this.popupComponent) {
return;
}
if (moment(this.dateOfBirth).isToday()) {
this.popupComponent.showPopup(`Happy birthday, ${this.name}!`);
}
}
}
typescript
@Component
class GreeterComponent extends BaseComponent {
@Prop({required: false}) name?: string;
@Prop({required: false}) dateOfBirth?: string;
@Ref messageSpan: HTMLElement;
popupComponent: null|PopupComponent = null;
init() {
this.messageSpan.textContent = `Hey, ${this.name || 'customer'}!`;
// Register event handlers
this.customer.change.subscribe(this.handleCustomerChanged);
// Create elements
this.popupComponent = document.createElement('popup-component');
document.body.appendChild(this.popupComponent);
this.checkBirthday();
}
destroy() {
// Unregister event handlers
this.customer.change.unsubscribe(this.handleCustomerChanged);
// Clean up elements
this.popupComponent.remove();
}
handleCustomerChanged(customer: null|Customer) {
this.name = customer?.name;
this.dateOfBirth = customer?.getDateOfBirth();
this.checkBirthday();
}
checkBirthday() {
if (!this.dateOfBirth || !this.popupComponent) {
return;
}
if (moment(this.dateOfBirth).isToday()) {
this.popupComponent.showPopup(`Happy birthday, ${this.name}!`);
}
}
}