Skip to content

Instantly share code, notes, and snippets.

@jayrbolton
Last active February 3, 2017 16:59
Show Gist options
  • Save jayrbolton/a763a3a8744fecf42842da18c1445cd5 to your computer and use it in GitHub Desktop.
Save jayrbolton/a763a3a8744fecf42842da18c1445cd5 to your computer and use it in GitHub Desktop.
Snabbdom transformer idea
// this is how you could create composable functions that modify and extend VNodes
// - append or prepend children
// - add surrounding VNode wrappers
// - compose hook and event functions
// - merge props, attrs, style, and class
// snabbdom-transform objects can have these properties
// - wrapper: function that takes the vnode and allows you to add surrounding elements
// - class, style, and attrs: these will merge with existing data using R.merge
// - on, hook: these functions will merge and get composed with existing on/hook functions without overwriting any
// - appendChildren, prependChildren: child vnodes to append and prepend
// You can wrap the transform in a function to 'configure' it
const wordCount = (limit, total$) => {
// This allows you to wrap the vnode in surrounding parent elements and siblings
// If another snabbdom-transformer has already applied a wrapper function, then this wrapper function will get applied
wrapper: vnode => h('div', [
vnode
, h('p', limit - total$() + ' words')
])
// If the vnode already has other event listeners functions, then snabbTransform will compose them together so none are overwritten
, on: {
keyup: ev => { total$(ev.currentTarget.value.split(' ').length }
}
// Any classes added here will merge with any other classes already on the vnode
, class: {
invalid: total$() > limit
}
, appendChildren: [x, y, z] // These elements will append to any existing children nodes
, prependChildren: [x, y, z] // These elements will prepend to existing children nodes
}
// Use these transforms with the snabbdom-transform module
const patch = snabbdom.init([/* .. other modules .. */, require('snabbdom-transform')])
// Then when you create VNodes, you can pass transforms into the 'transforms' property of the vnode's data:
const view = state => {
return h('textarea', {
props: {name: 'summary', placeholder: 'Briefly describe blah blah blah'}
, on: {keyup$: handleSummaryKeyup} // This will get composed with other keyup functions inside the transforms
, transforms: [
wordCount(10, state.summaryWordCount$)
, resizableTextbox
, validate(state.form, {required: true, minWords: 5, maxWords: 11})
]
})
}
// In the above we are applying three separate transforms that get composed together.
// Each one adds a "keyup" function handler and each one adds their own wrapper content.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment