As I understand there are basically two(+) ways of definining components in FAST.
I will provide my own answer to the question below, what I want to verify is whether I am correctly understanding the differences and if there is anything to add.
What I've found out so far:
One - Immediate Template & Style Resolution
- class definition extending
FASTElement
from@microsoft/fast-element
- uses
@customElement
decorator from@microsoft/fast-element
- it must contain
-
in its name - its template and style (passed through the
@customElement
decorator) are immediately resolved - it cannot extend its PartialFASTElementDefinition
- it cannot access ElementDefinitionContext when defining its template and style
Example pseudocode (parts from official docs):
const counterStyles = css`/* ... */`;
const counterTemplate = html<NameTag>`<!-- ... -->`;
@customElement({
name: 'name-tag',
counterTemplate,
counterStyles,
shadowOptions:
})
export class NameTag extends FASTElement {
@attr name = "Sally";
}
Two - Extendible and Lazy Template & Style Resolution
- class definition extending
Foundationelement
from@microsoft/fast-foundation
- it doesn't have to contain
-
in its name (since it will be prepended with the prefix of aDesignSystem
that will register it) - its template and style are resolved through the
compose
method that is made available to the component through itsFoundationElement
base class - both template and style can be lazily resolved
- lazy resolution has the benefit of giving you access to both ElementDefinitionContext and an extendible FoundationElementDefinition
Example pseudocode (parts from official docs):
export class Counter extends FoundationElement {
@attr count = 0;
increment() {
this.count++;
}
}
/* if CounterDefinition wouldny be defined then expressions below would use FoundationElementDefinition instead*/
interface CounterDefinition extends FoundationElementDefinition {
defaultButtonContent?: string;
defaultButtonColour?: string;
}
const counterStyles = (
context: ElementDefinitionContext,
definition: CounterDefinition
) => css`/* ... */`;
const counterTemplate = (
context: ElementDefinitionContext,
definition: CounterDefinition
) => html`<!-- ... -->`;
export const counter = Counter.compose<CounterDefinition>({
baseName: 'counter',
counterTemplate,
counterStyles,
defaultButtonContent: "Count!",
defaultButtonColour: "pink"
});
Three/One+ - Kindof One but without decorators?
- as I understand it is basically like method
One
but without decorators, meaning it cannot lazily resolve its styles and templates