The Archetype Component Pattern
One of my biggest challenges during my years working as a Frontend Developer has been finding a way to create components that can be shareable with an easy configuration, while at the same time managing to add value to the business.
Today I want to introduce to you an easy way to achieve this with a pattern that I call “The Archetype Pattern”.
The scaffolding
Let’s start with the folder structure:
-> app.module.ts
-> app.component.ts
-> archetype-one/schema/general-implementation.type.ts
-> archetype-one/schema/variation-one.type.ts
-> archetype-one/archetype-one.component.ts
-> archetype-one/archetype-one.component.html
-> archetype-one/archetype-one.component.scss
-> archetype-one/archetype-one.spec.component.ts
-> archetype-one/configuration.model.ts
-> archetype-one/actions.model.ts
-> archetype-one/archetype-one.module.ts
So far there is no change to a regular angular scaffolding. I recommend you always try to isolate your components as much as possible. This can be achieved by creating modules for each shareable feature, and on this post I’ll define this as an Archetype.
Basic architecture of an Archetype
An Archetype consists of a shareable component with one configuration ‘@input’ and one action message informer ‘@output’. This basic configuration is all you need to hold all the required information to display the data in your view and inform the parent component of the necessary user interactions.
Let’s see the component implementation so far:
The component logic
import types, ArchetypeOneActionModel from "./actions.model"@Component({
selector: "archetype-one"
templateUrl: "./archetype-one.component.html"
styleUrls: ["./archetype-one.component.scss"]
})export class ArchetypeOneComponent {
@input() config: ConfigurationModel;
@output() actions: : EventEmitter<ArchetypeOneAcionModel> = new EventEmitter(); public informClickToParent() {
this.actions.emit({type: types.MAIN_BUTTON_CLICKED});
}
}
The component HTML
<button (click)="informClickToParent()"></button>
The Actions data bus is an ‘eventEmmitte’ which informs the parent the name of the interaction on ‘$event.type’ property and an optional property called payload on ‘$event.payload’. In your own implementation, the type of the payload could be more specific, for example it could be a string if you want to inform a ‘url’ after the user clicks on a button.
The Configuration model, the schemas and the actions
Let me explain a little bit more about some of the files that we will use during your archetype creation.
- The ‘configuration.model.ts’ contains the archetype required data to render the view.
export interface ConfigurationModel {
label: string
}
- The ‘schema/general-implementation.type.ts’ holds the first implementation of the Archetype. You must create one of these files for each variation of your component.
export const GENERAL_IMPLEMENTATION: ConfigurationModel = {
label: "my generic label"
}
- The ‘actions.model.ts’ holds the interface with the actions configuration. It must have a ‘type’ property with the name of the interaction and an optional ‘payload’ property which has additional information. Also, you need to export an object with all the available actions types.
MAIN_BUTTON_CLICKED = "MAIN_BUTTON_CLICKED";
SECONDARY_BUTTON_CLICKED = "SECONDARY_BUTTON_CLICKED";// The available actions typesexport const types = {
MAIN_BUTTON_CLICKED,
SECONDARY_BUTTON_CLICKED
}// The event emitter typeexport interface ArchetypeOneAcionModel {
type: string;
payload?: any;
}
How to use an Archetype
To use an archetype you need three things: First, you need to register the module where it’s needed. After, you need to define which configuration to use. This is the moment where you use one of your ‘schemas’. Finally, you need to create a method which listens for all your actions and executes the desired behavior.
Let’s see how it looks like with a live version:
Parent html component
<archetype-one [config]="configuration"
(actions)="componentActions($event)"></archetype-one>
Parent component
import GENERAL_IMPLEMENTATION from "../archetype-one/schema/general-implementation.type"
import types, ArchetypeOneActionModel from "../archetype-one/actions.model"export class ParentComponent {
configuration = GENERAL_IMPLEMENTATION; actionsDispatcher(action: ArchetypeOneAcionModel) {
switch(event.type) {
case: types.MAIN_BUTTON_CLICKED: {
// do something
break;
}
}
}
}
Conclusion
The whole purpose of this post is to show you a pattern that you could use in your angular projects to have reusables components focused on the view. In the next post I’ll introduce you to a useful service you can use to change the content of your archetype on the fly.
This is my first post on Medium, so I hope you enjoyed it and it’s worth your claps :). Thanks for reading!