foxhound87 / mobx-react-form

Reactive MobX Form State Management
https://foxhound87.github.io/mobx-react-form
MIT License
1.09k stars 129 forks source link

how to set form values from props? #194

Closed brandonmp closed 7 years ago

brandonmp commented 7 years ago

I must be missing something super obvious b/c this seems like a really basic use case, but I can't figure out how to set initial values w/ props and then handle user inputs normally (ie, keystrokes aren't registered).

I've adapted your example from the tutorial:

// fields.js
const makeFields = (currentUser) => {
  const fields = {
    email: {
      label: 'Email',
      placeholder: 'Insert Email',
      value: currentUser.emailAddress,
      rules: 'required|email|string|between:5,25',
    },
    password: {
      label: 'Password',
      placeholder: 'Insert Password',
      rules: 'required|string|between:5,25',
    },
  }
  return fields
}

export default makeFields
// form.js
import MobxReactForm from 'mobx-react-form'

class NewUserForm extends MobxReactForm {

  onSuccess(form) {
    alert('Form is valid! Send the request here.')
    // get field values
    console.log('Form Values!', form.values())
  }

  onError(form) {
    // get all form errors
    console.log('All form errors', form.errors())
    // invalidate the form with a custom error message
    form.invalidate('This is a generic error message!')
  }
}

export default NewUserForm
// FormView.js
import NewUserForm from './form.js'
import makeFields from './fields.js'
import validatorjs from 'validatorjs'
import { observer } from 'mobx'
// ...

@observer
class MyForm extends Component {

  render() {
     const fields = makeFields(this.props.currentUser)
    const form = new NewUserForm({ fields }, { plugins: { dvr: validatorjs } })
    return (
       <form>
          <label htmlFor={form.$('email').id}>
            {form.$('email').label}
          </label>
          <input {...form.$('email').bind() } />
          <p>{form.$('email').error}</p>

          <label htmlFor={form.$('password').id}>
            {form.$('password').label}
          </label>
          <input {...form.$('password').bind({ type: 'password' }) } />
          <p>{form.$('password').error}</p>

           <button type='submit' onClick={form.onSubmit}>Submit</button>

           <p>{form.error}</p>
         </form>
    )
}

As i mentioned, the initial value populates fine, but keystrokes in the input field don't register.

Am I missing something simple here?

ETA: I've also tried passing in state as value, but no dice.

foxhound87 commented 7 years ago

Hi @brandonmp

which version of mobx, mobx-react and mobx-react-form are you using?

What "keystrokes in the input field don't register" mean? The input value changes into the input and the form state is not updated OR the input values are not updated and they remain fixed into the input?

The observer method is not part of mobx but you should import mobx-react instead: import { observer } from 'mobx-react';

You can try to place makeFields() function and the form initialization outside the react render() method.

As you are using arrow function for makeFields(), you don't need to use return, just do:

const makeFields = currentUser => ({
  email: {
    label: 'Email',
    placeholder: 'Insert Email',
    value: currentUser.emailAddress,
    rules: 'required|email|string|between:5,25',
  },
  password: {
    label: 'Password',
    placeholder: 'Insert Password',
    rules: 'required|string|between:5,25',
  },
});

If you didn't fixed it yet, then you should review you app structure and maybe the babel plugins and presets you are using.

Anyway I suggest you to use react stateless functional components as much as you can.

foxhound87 commented 7 years ago

I close this issue for inactivity.

Feel free to reopen this if you need more help.