anthonyshort / deku

Render interfaces using pure functions and virtual DOM
https://github.com/anthonyshort/deku/tree/master/docs
3.41k stars 130 forks source link

Question: Custom attributes #402

Closed 11111000000 closed 8 years ago

11111000000 commented 8 years ago

Example case: instead of <input onKeyDown={ handleDivKeyDown } /> when user only want to handle Enter key, we prefer to code like this: <input onPressEnter={ doJob } /> . Is there some dekujs-way? Or maybe better to use <SuperInput with={neededFeatures} /> ?

ashaffer commented 8 years ago

You could accomplish this with a custom element function. E.g.

import _element from 'virtual-element'

function element (tag, attrs, ...children) {
  forEach(attrs, (val, key) {
    if (key === 'onPressEnter') {
      delete attrs[key]
      attrs['onKeyDown'] = function () {
        if (e.which === 13) {
          val(e)
        }
      })
    }
  })
}

My personal preference for this though is to have an element function that accepts a map, like this:

function render () {
  return <input onKeyDown={{enter: doJob}} />
}

I've made a small library: keychord that would be useful for this. In virtex-element, I also let it accept arrays. So that you can, say for an input do:

function render () {
  return <input onKeyDown={[{enter: doJob}, updateText]} />
}

Which lets you write more declarative event handlers, even when you want to branch on the type of event it is.

Perhaps an even better and more generic solution would be to create some sort of event handler library that does this:

import element from 'virtual-element'
import ev from 'create-handler'

function render () {
  return <input onKeyDown={ev([{enter: doJob}, updateText]} />
}

That doesn't require any changes to deku or a custom element function.

11111000000 commented 8 years ago

Awesome! Thanks you!

ashaffer commented 8 years ago

I went ahead and created the module: event-handler.

11111000000 commented 8 years ago

Solved completely!

anthonyshort commented 8 years ago

Great! I was basically going to suggest the same thing :) Going to add a tag to this so I remember to add it to the docs.