View component for markup you already have.
Features:
Inspired by:
npm install figura --save
<div id="shelby">
<span id="sasha">
<button type="button" class="lilly">Lilly button</button>
<span class="honey">Honey content</span>
</span>
<i class="roxie">Roxie content</i>
</div>
import Figura from 'figura';
class Shelby extends Figura {
static el = '#shelby';
static childrenEl = {
sasha: '#sasha'
};
static events = {
'click .lilly': 'clickMethod'
};
clickMethod() {
// .lilly clicked!
}
}
class Sasha extends Shelby {
static el = '#sasha';
static childrenEl = {
...Shelby.childrenEl,
honey: '.honey'
};
clickMethod() {
// .lilly clicked, with overriden method on `Sasha`.
}
}
const shelby = new Shelby();
// `roxie` won’t have any child elements and won’t have any event listeners since it doesn’t have any children nodes
const roxie = new Sasha({
el: '.roxie'
});
Using state and props. All render specifics can be contained inside render
method.
import Figura from 'figura';
class Shelby extends Figura {
static el = '#shelby';
static defaultProps = {
text: 'shelby'
};
constructor(props) {
super(props);
this.render(); // Initial render only with props
this.setState({
jackie: 42,
romeo: '42'
});
const state = this.state;
state.jackie; // => 42 as number
}
render(key, value) {
if (typeof key === 'undefined') {
this.$el.innerHTML = `Initial content is ${this.props.text}.`; // Initial content is shelby.
}
if (key === 'romeo') {
this.$el.innerHTML = `Value is ${value}.`; // Value is 42.
}
return this;
}
}
Render placeholder and view assign usage.
import Figura from 'figura';
class Shelby extends Figura {
static el = '#shelby';
template() {
// Template function result
}
constructor(props) {
super(props);
this.addSubview(new Figura(), 'customKey');
}
render() {
this.$el.innerHTML = this.template({
customKeyComponent: this.getSubview(
'customKey'
).getRenderPlaceholder()
});
this.assignSubview('customKey');
return this;
}
}
Every property except el
, childrenEl
and events
will be merged with
defaultProps
and added to this.props
.
Type: (string|HTMLElement)
Default: ``
Element on which should view be created.
Type: Object
Default: {}
List of children elements, mapped to DOM nodes based on CSS selector.
To handle common use case of selecting only one element, if result contains only one element, only that element is returned, otherwise array of elements is returned.
If you want to return array of elements regardless of resulting count, append
[]
to list key.
{
'shelby': '.shelby', // this.$shelby = this.$('.shelby'); - Returns either one or array of elements, based on resulting count
'sasha': '.sasha' // this.$sasha = this.$('.sasha'); - Returns either one or array of elements, based on resulting count
'rudy[]': '.rudy' // this.$rudy = this.$('.rudy'); - Always returns array of elements
}
Type: Object
Default: {}
List of events, delegated to children elements.
There are certain considerations to take when using Figura’s event delegation:
focus
and blur
events is not natively possible, thosefocusin
and focusout
respectivelyel
property value).{
'click .shelby': 'method1', // Delegated click event to `.shelby` calling instance method `method1`
'submit .sasha': 'method2', // Delegated submit event to `.sasha` calling instance method `method2`
'mouseleave .lilly': 'method3', // Delegated mouseleave event to `.lilly` calling instance method `method3`
'mouseenter .rudy': ( e ) { // Delegated mouseenter event to `.rudy` calling anonymous function
// Do something
},
'click': 'method4' // Attached to root element since there is no selector to delegate to
}
Type: Function
Default: {}
Default values for props to ensure that this.props
property has value if it
hasn’t been passed when creating view instance.
Type: Function
Returns: (HTMLElement|HTMLElement[])
Finds all descendants of $el
filtered by CSS selector.
Property | Type | Default | Description |
---|---|---|---|
selector |
string |
N/A | Standard CSS selector. |
returnAllNodes |
boolean |
false |
Always return array of elements. By default, if result contains only one element only that element is returned, if result doesn’t contain any element null is returned, otherwise array of elements is returned. |
Type: Function
Returns: Figura
Render view. Takes into account state modifications if you use state—every time
state is modified render
is called with key which is changed and current
state. In this instance, state is combination of previous and new state.
Property | Type | Description |
---|---|---|
key |
string |
Current state key that should be handled in render . |
value |
* |
Value of current state key that should be handled in render . |
Type: Function
Remove view, but not root DOM element—use removeElement
for
that.
Type: Function
Sets or re-sets current UI element.
Type: (string|HTMLElement)
Type: Function
Remove view DOM element.
Type: Function
Caches children elements.
Type: Object
See childrenEl
.
Type: Function
Delegates events.
Type: Object
See events
.
Type: Function
Undelegates events.
Type: Function
Delegate single event.
If you provide empty string selector, event will be attached to root element.
Type: string
Type: string
Type: Function
Type: Function
Undelegate single event. For argument definition, see
delegate
.
Type: Function
Set state for instance. Runs synchronously, so if one piece of state depends on
other (e.g. one key depends on another key), run multiple setState
calls with
different keys.
Adds subview to current view.
Type: Figura
Subview to add to current view.
Type: (string|number)
Subview key so it can be easily identified in subview collection. If undefined,
view’s uid
property will be used.
Gets subview referenced by key.
Type: (string|number)
Key which is used to reference subview.
Removes all subviews from current view.
Returns view’s placeholder element which will be used in resolving for
assignSubview
.
Replaces view’s render placeholder with real content. Real content should be
rendered inside subview render
method.
Type: (string|number)
Key which is used to reference subview.
Add side effect. See manageSideEffects.add
documentation.
Remove side effect. See manageSideEffects.remove
documentation. Every registered side effect is removed on remove
method call.
Running setState
on multiple keys which depend on each other in that call
doesn’t render changes properly.
setState
runs synchronously, so if one piece of state depends on other (e.g.
one key depends on another key in current setState
call), run multiple
setState
calls.
For example, if romeo
and layla
values depend on each other in current
setState
call:
// Instead of this
this.setState({
romeo: 'gigi',
layla: 'buddy'
});
// Use this
this.setState({
romeo: 'gigi'
});
this.setState({
layla: 'buddy'
});
Communicating with parent component from child component
There are a lot of ways you can achieve this:
For local automated tests, run npm run test:automated:local
.
Tested in IE9+ and all modern browsers. For IE <= 10
support, you will have to polyfill
__proto__
if you use class extending.
For static class properties, you need to use Babel plugin, otherwise set properties explictly on class.
import Figura from 'figura';
// With static class properties
class Shelby extends Figura {
static el = '';
}
// Without static class properties
class Shelby extends Figura {}
Shelby.el = '';
MIT © Ivan Nikolić