Как сбросить поля формы до значения по умолчанию в cycle.js

У меня есть кусок кода, использующий cycle.js и реактивную библиотеку xstream, как показано ниже. Он состоит из поля формы, значение которого отображается в теге ap при отправке. Далее следуют вопросы: 1. Как можно изменить поле ввода формы на значение по умолчанию при отправке формы? 2. Есть ли способ сбросить input$ и отправить $ streams к их начальным значениям после submit?

function formIntent (sourcesDOM) {
  const fNameInput$ = sourcesDOM
    .select('form#user .fname')
    .events('input')
    .compose(debounce(1000))
    .map((e: {target: any}) => e.target.value)

  const submit$ = sourcesDOM
    .select('form#user')
    .events('submit')
    .map((e) => e.preventDefault())
    .mapTo({type: 'USER'})

  const actions$ = xs.combine(fNameInput$, submit$)

  const initState = {fNameInput: ''}

  return actions$
    .map(([fNameInput, {type}]) => {
      return type === 'USER' ? {fNameInput} : initState
    })
    .startWith(initState)
}

function formView (state$) {
  return state$
    .map(({fNameInput}) => 
      div([
        form('#user', [
          label('Name'),
          hr(),
          input('.fname', {attrs: {id: 'first-name', type: 'text', placeholder: 'First name'}}),
          hr(),
          input('.sub', {attrs: {type: 'submit', value: 'Save'}})
        ]),
        div([
          h2('Submitted value'),
          p(fNameInput),
          hr()
        ])
      ])
    )
}

Есть ли лучший способ создать такую ​​форму? PS вывод функции formIntent подается на вход функции formView.

2 ответа

Вы можете использовать ловушку для обновления входного значения при обновлении DOM. Так что если вы используете @cycle/dom version >11.0, которая использует Snabbdom, вы можете использовать это так:

input({
    hook: {
        update: (o, n) => n.elm.value = ''
    }
})

Где пустая строка, вы можете передать значение по умолчанию, которое вы хотите. Он будет обновлять входное значение каждый раз, когда состояние обновляется.

Это то, что я в итоге сделал. Это делает то, что я хотел. Мне все еще будет интересно узнать лучший способ достижения той же цели.

function formIntent (sourcesDOM) {
  const fNameInput$ = sourcesDOM
    .select('form#user .fname')
    .events('input')
    .compose(debounce(1000))
    .filter((e: {target: any}) => e.target.value.length > 2)
    .map((e: {target: any}) => e.target)

    const submit$ = sourcesDOM
    .select('form#user')
    .events('submit')
    .map(e => {
      e.preventDefault()
      console.log('3: Inside intent', e)
      return {user: 'CLICKED'}
    })

  return xs.combine(fNameInput$, submit$)
}

function formModel (actions$) {
  const initState = {user: '', fNameInput: {}}
  return actions$
    .map(([fNameInput, user]) => {
      const fName = fNameInput.value
      if (user.user === 'CLICKED') {
         fNameInput.value = fNameInput.defaultValue
         user.user = 'DISPLAY'
         return {user: user.user, fNameInput: fName}
      } else return initState
    })
    .startWith(initState)
}

function formView (state$) {
  return state$
    .map(({user, fNameInput}) =>
      div([
        form('#user', [
          label('Name'),
          hr(),
          input('.fname', {attrs: {id: 'first-name', type: 'text', placeholder: 'First name'}}),
          hr(),
          input('.sub', {attrs: {type: 'submit', value: 'Save'}})
        ]),
        (user === 'DISPLAY') && div([
          h2('Submitted value'),
          p(fNameInput),
          hr()
        ])
      ])
    )
}

function main (sources) {
  const actions$ = formIntent(sources.DOM)
  const state$ = formModel(actions$)
  const vtree$ = formView(state$)

  return {
    DOM: vtree$
  }
}
Другие вопросы по тегам