Sugar provide a nice stack for webcomponent development. This stack is basically composed of the SWebComponent
js class that abstract a lot of dirty work work you like:
- Listen for attributes changes
- Mount the component at a certain point in time (inViewport, visible, etc...)
- Automatically cast the attributes to their proper js variable types (Array, Object, String, etc...)
- Physical props : Specify some props that will ALWAYS be present as attribute on the component for styling purpose
- Define some default CSS that will be injected in the head automatically
- Specify some required props
- Full lifecycle management:
- componentCreated
- componentWillMount
- componentMount
- shouldComponentAcceptProp
- componentWillReceiveProp
- componentWillReceiveProps
- shouldComponentUpdate
- render
- componentUnmount
- Mount dependencies : This will allows you to set some promises that have to be resolved before mounting the component
- Get Started
- Lifecycle
- Props
- State
- Mount when
- Mount dependencies
- Default CSS
- Component boilerplate
- Full SWebComponent API documentation
Here's how to use the SWebComponent
class :
import SWebComponent from 'coffeekraken-sugar/js/core/SWebComponent'
class MyCoolComponent extends SWebComponent {
/**
* Default state
* @definition SWebComponent.defaultState
* @protected
*/
static get defaultState() {
return {
};
}
/**
* Default props
* @definition SWebComponent.defaultProps
* @protected
*/
static get defaultProps() {
return {
};
}
/**
* Physical props
* @definition SWebComponent.physicalProps
* @protected
*/
static get physicalProps() {
return [];
}
/**
* Css
* @protected
*/
static defaultCss(componentName, componentNameDash) {
return `
${componentNameDash} {
display : block;
}
`;
}
/**
* Component will mount
* @definition SWebComponent.componentWillMount
* @protected
*/
componentWillMount() {
super.componentWillMount();
}
/**
* Mount component
* @definition SWebComponent.componentMount
* @protected
*/
componentMount() {
super.componentMount();
}
/**
* Component unmount
* @definition SWebComponent.componentUnmount
* @protected
*/
componentUnmount() {
super.componentUnmount();
}
/**
* Component will receive prop
* @definition SWebComponent.componentWillReceiveProp
* @protected
*/
componentWillReceiveProp(name, newVal, oldVal) {
switch(name) {
}
}
}
// define your component
MyCoolComponent.define('my-cool-component', MyCoolComponent);
Each component will have his own lifecycle. Here it is:
componentCreated
: When the component has being created in memorycomponentWillMount
: Callded before the component is actually mounted and before the mountDependencies are resolvedcomponentMount
: When the component is actually mountedcomponentWillReceiveProp(prop, newVal, oldVal)
: When the component receive a new propertycomponentWillReceiveProps(nextProps)
: When the component receive some new properties. It will be called after the componentWillReceiveProp with all the updated properties at oncerender
: Method called to update the DOM depending on the propscomponentUnmount
: Called when the component is unmouted
Don't forget to call the
super.{methodName}
to ensure that you don't skip important features executions.
Each component expose his "state" through the this.props
object. These props are reachable and settable through several methods:
#### Set a prop :
<my-component {propName}="{propValue}"></my-component>
this.setProp(prop, value)
this.setProps(propsObj)
this.props.{propName} = {propValue}
: This use the Proxy capabilities of modern browsers. Try to use instead thethis.setProp
function to avoid issues with older browsers like IE11...
const myProp = this.props.{propName}
const myProp = this.getProp({propName})
Avoid using names of properties that already exists on the HTMLElement object. If you do so, you can have some unexpected issues...
Each component expose his internal state through the this.state
object. These props are reachable and settable through several methods:
#### Set the state :
this.setStateValue(prop, value)
this.setState(stateObj)
this.state.{propName} = {propValue}
: This use the Proxy capabilities of modern browsers. Try to use instead thethis.setProp
function to avoid issues with older browsers like IE11...
const myStateValue = this.state.{propName}
const myStateValue = this.getState({propName})
You can specify when you want your component to be mounted by using the mountWhen
property. Here's the possible values
inViewport
: Mount the component when it is/enter the viewportmouseover
: Mount the component when the user mouseover itvisible
: Mount the component when the component is/became visible{function}
: A function that need to return a promise resolved when you want the component to be mounted
You can specify some dependencies that the component has to respond before being mounted. This is useful to check that the context is ok for the component to be inited. Maybe your component need to be nested in another one and has to wait that this one has been inited before mounting itself... Here's how to proceed:
class MyCoolComponent extends SWebComponent {
/**
* Mount dependencies
* @definition SWebComponent.mountDependencies
* @protected
*/
static get mountDependencies() {
// return an array of promised that represent your dependencies...
return [function() {
// here, the "this" will refer to the component instance
// !!! do not use the arrow => function notation, otherwise the "this" will not be correctly bound...
return new Promise((resolve) => {
// your dependency logid here...
setTimeout(resolve, 2000);
});
}]
}
}
You can easily define some default CSS for your component. This has to be done like so:
class MyCoolComponent extends SWebComponent {
/**
* Default CSS
* @definition SWebComponent.defaultCss
* @protected
*/
static defaultCss(componentName, componentNameDash) {
return `
${componentNameDash} {
display : block;
}
.${componentNameDash}__item {
// something...
}
// etc...
`;
}
}
The custom elements specification allows to extend native DOM elements. You can has well do that through the SWebComponent
class. Here's how to process:
import native from 'coffeekraken-sugar/js/core/sNativeWebComponent'
class MyCoolInputComponent extends native(HTMLInputElement) {
// component implementation...
}
MyCoolInputComponent.define('my-cool-input', MyCoolInputComponent, 'input');
You can see two things here:
- The component extends the
HTMLInputElement
class - The
HTMLInputElement
is passed to thenative
function that abstract some dark instructions to allow the extend to work properly with native HTMLElement - The component is defined with a third parameter that represent the native DOM element to extend
You can now use your input component using the is notation like so:
<input type="text" is="my-cool-input" />
We provide a nice boilerplate to dive right into your component development without the trouble of configuring anything.