Choo: contentedtiable elements.

Created on 22 Jun 2016  路  9Comments  路  Source: choojs/choo

const choo = require('choo')
const app = choo()

app.model({
  state: { title: 'Set the title' },
  reducers: {
    update: (action, state) => ({ title: action.value })
  }
})

const mainView = (params, state, send) => choo.view`
  <main>
    <h1>${state.title}</h1>
    <div
      contenteditable="true"
      oninput=${(e) => send('update', { value: e.target.value })}>Type here</div>
  </main>
`

app.router((route) => [
  route('/', mainView)
])

const tree = app.start()
document.body.appendChild(tree)

Doesn't update the state, missing something?

Most helpful comment

This works:

const choo = require('choo')
const app = choo()

app.model({
  state: { title: 'Set the title' },
  reducers: {
    update: (action, state) => ({ title: action.value })
  }
})

const mainView = (params, state, send) => choo.view`
  <main>
    <h1>${state.title}</h1>
    <div
      contenteditable="true"
      oninput=${(e) => send('update', { value: e.target.innerText })}>${state.title}</div>
  </main>
`

app.router((route) => [
  route('/', mainView)
])

const tree = app.start()
document.body.appendChild(tree)

The reason is that you're sending the value of the <div> but not changing it. Every call to oninput causes the DOM to update based on the current value of the state.

So you delete the type here and it sends an oninput with e.target.innerText equal to '', and updates the state. Then it re-renders. But you haven't changed what the input value for the contenteditable is, so it's still type here when you go to type in it.

You delete, it sends, resets to type here, rerenders, etc.

You need to track the state in the element which is sending the updates as well since the state is the source of truth, not the DOM.

All 9 comments

Are you in Firefox?

some versions of firefox don't trigger oninput on conteneditable

@toddself Sorry forgot the mention. Chrome OSX: Version 51.0.2704.103 (64-bit) that snippet works fine for you?

I am doing bedtime with my kids on I am on the phone. I see no immediate gotchas though. Can you confirm your reducer fires with a log or a breakpoint?

It is getting triggered, but action's value is not defined. Object {type: "update", value: undefined} requirebin for reference.

screen shot 2016-06-22 at 9 52 40 am

@toddself Hope you are still awake ;)

<div>s don't have a value property - your looking for innerText. Here's an example of a content editable div in a choo app.

@timwis duh, value...same with innerText or textContent, could you please have a look at the requirebin thinge?

The reducer

update: (action, state) => ({ title: action.innerText })

should be:

update: (action, state) => ({ title: action.value })

because your send uses value as its key:

send('update', { value: e.target.innerText })

@timwis That was the first thing /me tried, it results in this

This works:

const choo = require('choo')
const app = choo()

app.model({
  state: { title: 'Set the title' },
  reducers: {
    update: (action, state) => ({ title: action.value })
  }
})

const mainView = (params, state, send) => choo.view`
  <main>
    <h1>${state.title}</h1>
    <div
      contenteditable="true"
      oninput=${(e) => send('update', { value: e.target.innerText })}>${state.title}</div>
  </main>
`

app.router((route) => [
  route('/', mainView)
])

const tree = app.start()
document.body.appendChild(tree)

The reason is that you're sending the value of the <div> but not changing it. Every call to oninput causes the DOM to update based on the current value of the state.

So you delete the type here and it sends an oninput with e.target.innerText equal to '', and updates the state. Then it re-renders. But you haven't changed what the input value for the contenteditable is, so it's still type here when you go to type in it.

You delete, it sends, resets to type here, rerenders, etc.

You need to track the state in the element which is sending the updates as well since the state is the source of truth, not the DOM.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

depoulo picture depoulo  路  3Comments

sholtomaud picture sholtomaud  路  4Comments

wenkesj picture wenkesj  路  3Comments

tornqvist picture tornqvist  路  4Comments

awesomektvn picture awesomektvn  路  5Comments