1
votes

I have a Formik form where I am trying to render a Formik field. However, the field is a currency field and onBlur is triggered I want to clean up the field format. I am attempting to wrap the Formik field around a TextField. To do so, in Form.js I have:

<Form>
 <Field
   component={ MoneyField }
   name='cover'
   variant='outlined'
   label='Cover'
   fullWidth
   InputProps={{ startAdornment: <InputAdornment position='start'>$</InputAdornment> }} />
<Button
  type='submit'
  variant='contained'
  color='primary' 
  fullWidth>
  Submit
 </Button>

Then my custom money field component MoneyField.js:

const MoneyField = ({ field, form, ...props }) =>{
  const { name, value } = field 

  function formatInputToMoney(e) {
    let cover = e.target.value.match(/\d+\.?/g)

    cover = cover === null ? 0 : parseFloat(cover.join(''))
    form.values[name] = formatMoney(cover).replace('$', '')
  }

  return ( 
    <TextField
      onBlur={ formatInputToMoney } 
      { ...props } />
  )
}

export default MoneyField

The above works and when a user changes the input the value in the form gets updated. However, if I don't have the form.values[name] line where I call the form to directly update its value, the value would get updated in the input box but not in the form object, so if I change the value to 5 in the input field I would see that change but when the form is submitted the initial value of 0 would get passed.

Is there a more efficient way to create a subcomponent of Field where the form values update based on the subcomponent without calling the form thats passed by Formik directly?

1

1 Answers

0
votes

You need to call setFieldValue on the formik form in order to set field value https://jaredpalmer.com/formik/docs/api/formik#setfieldvalue-field-string-value-any-shouldvalidate-boolean-void in Formik's form which gets submitted. Once formik updates form model, it will cause re-render of your component which will display updated value to you.

const MoneyField = ({ field, form, ...props }) =>{
  const { name, value } = field 

  function formatInputToMoney(e) {
    let cover = e.target.value.match(/\d+\.?/g)

    cover = cover === null ? 0 : parseFloat(cover.join(''))
    form.setFieldValue(name, formatMoney(cover).replace('$', ''));
  }

  return ( 
    <TextField
      onBlur={ formatInputToMoney } 
      { ...props } />
  )
}

export default MoneyField