最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I change a Formik TextField value from the outside of the From? - Stack Overflow

programmeradmin2浏览0评论

On a module dialog, I want to change the value of input value (#quaggaIsbn). I tried document.getElementById("quaggaIsbn").value = result.codeResult.code but it wasn't reflected to the values the form sends to the server. How can I change the values Formik sends to the server?

NewProjectDialog.js

import React from 'react';
import PropTypes from 'prop-types'
import { Formik, Field, Form } from 'formik'
import { TextField} from 'formik-material-ui'
import { makeStyles } from '@material-ui/core/styles'
import Button from '@material-ui/core/Button'
import Dialog from '@material-ui/core/Dialog'
import DialogTitle from '@material-ui/core/DialogTitle'
import DialogActions from '@material-ui/core/DialogActions'
import DialogContent from '@material-ui/core/DialogContent'
import styles from './NewProjectDialog.styles'
import Quagga from 'quagga';

const useStyles = makeStyles(styles)

function NewProjectDialog({ onSubmit, open, onRequestClose }) {
  const classes = useStyles()

  function handleSubmit(values, { setSubmitting }) {
    return onSubmit(values).then(() => {
      setSubmitting(false)
    })
  }



  function inputFile(){
    const file = document.getElementById("quaggaFile").files[0];
    const reader = new FileReader();
    reader.addEventListener("load", function () {
      // convert image file to base64 string
      analyzeQuaggaFile(reader.result);
      //preview.src = reader.result;
    }, false);
    reader.readAsDataURL(file);
  }

  function analyzeQuaggaFile(src){
  Quagga.decodeSingle({
//    src: "/image-002.jpg",
    src: src,
    numOfWorkers: 0,  // Needs to be 0 when used within node
    inputStream: {
        size: 800  // restrict input-size to be 800px in width (long-side)
    },
    decoder: {
        readers: ["ean_reader"] // List of active readers
    },
  }, function(result) {
      if(result.codeResult) {
          console.log("result", result.codeResult.code);
          document.getElementById("quaggaIsbn").value = result.codeResult.code  ;
      } else {
          console.log("not detected");
      }
  });
}

  return (
    <Dialog open={open} onClose={onRequestClose}>
      <DialogTitle id="new-project-dialog-title">Sell book</DialogTitle>

      <Formik initialValues={{ name: '' }} onSubmit={handleSubmit}>
        {({ errors, isSubmitting }) => (
          <Form className={classes.root}>
            <DialogContent>
              <Field
                id="quaggaIsbn"
                name="isbn"
                label="ISBN"
                ponent={TextField}
                margin="normal"
                fullWidth
              />
              Scan bar code:<input id="quaggaFile" type="file" accept="image/*" capture="camera" onChange={inputFile}/>
              <Field
                name="title"
                label="Title"
                ponent={TextField}
                margin="normal"
                fullWidth
              />
              <Field
                name="status"
                label="Status"
                ponent={TextField}
                margin="normal"
                fullWidth
              />
              <Field
                name="price"
                label="Price"
                ponent={TextField}
                margin="normal"
                fullWidth
              />
              Book cover:<input id="image" type="file"/>
            </DialogContent>
            <DialogActions>
              <Button onClick={onRequestClose} color="secondary">
                Cancel
              </Button>
              <Button type="submit" color="primary" disabled={isSubmitting}>
                {isSubmitting ? 'Creating...' : 'Create'}
              </Button>
            </DialogActions>
          </Form>
        )}
      </Formik>


    </Dialog>
  )
}

NewProjectDialog.propTypes = {
  onSubmit: PropTypes.func.isRequired,
  open: PropTypes.bool.isRequired,
  onRequestClose: PropTypes.func.isRequired
}

export default NewProjectDialog

On a module dialog, I want to change the value of input value (#quaggaIsbn). I tried document.getElementById("quaggaIsbn").value = result.codeResult.code but it wasn't reflected to the values the form sends to the server. How can I change the values Formik sends to the server?

NewProjectDialog.js

import React from 'react';
import PropTypes from 'prop-types'
import { Formik, Field, Form } from 'formik'
import { TextField} from 'formik-material-ui'
import { makeStyles } from '@material-ui/core/styles'
import Button from '@material-ui/core/Button'
import Dialog from '@material-ui/core/Dialog'
import DialogTitle from '@material-ui/core/DialogTitle'
import DialogActions from '@material-ui/core/DialogActions'
import DialogContent from '@material-ui/core/DialogContent'
import styles from './NewProjectDialog.styles'
import Quagga from 'quagga';

const useStyles = makeStyles(styles)

function NewProjectDialog({ onSubmit, open, onRequestClose }) {
  const classes = useStyles()

  function handleSubmit(values, { setSubmitting }) {
    return onSubmit(values).then(() => {
      setSubmitting(false)
    })
  }



  function inputFile(){
    const file = document.getElementById("quaggaFile").files[0];
    const reader = new FileReader();
    reader.addEventListener("load", function () {
      // convert image file to base64 string
      analyzeQuaggaFile(reader.result);
      //preview.src = reader.result;
    }, false);
    reader.readAsDataURL(file);
  }

  function analyzeQuaggaFile(src){
  Quagga.decodeSingle({
//    src: "/image-002.jpg",
    src: src,
    numOfWorkers: 0,  // Needs to be 0 when used within node
    inputStream: {
        size: 800  // restrict input-size to be 800px in width (long-side)
    },
    decoder: {
        readers: ["ean_reader"] // List of active readers
    },
  }, function(result) {
      if(result.codeResult) {
          console.log("result", result.codeResult.code);
          document.getElementById("quaggaIsbn").value = result.codeResult.code  ;
      } else {
          console.log("not detected");
      }
  });
}

  return (
    <Dialog open={open} onClose={onRequestClose}>
      <DialogTitle id="new-project-dialog-title">Sell book</DialogTitle>

      <Formik initialValues={{ name: '' }} onSubmit={handleSubmit}>
        {({ errors, isSubmitting }) => (
          <Form className={classes.root}>
            <DialogContent>
              <Field
                id="quaggaIsbn"
                name="isbn"
                label="ISBN"
                ponent={TextField}
                margin="normal"
                fullWidth
              />
              Scan bar code:<input id="quaggaFile" type="file" accept="image/*" capture="camera" onChange={inputFile}/>
              <Field
                name="title"
                label="Title"
                ponent={TextField}
                margin="normal"
                fullWidth
              />
              <Field
                name="status"
                label="Status"
                ponent={TextField}
                margin="normal"
                fullWidth
              />
              <Field
                name="price"
                label="Price"
                ponent={TextField}
                margin="normal"
                fullWidth
              />
              Book cover:<input id="image" type="file"/>
            </DialogContent>
            <DialogActions>
              <Button onClick={onRequestClose} color="secondary">
                Cancel
              </Button>
              <Button type="submit" color="primary" disabled={isSubmitting}>
                {isSubmitting ? 'Creating...' : 'Create'}
              </Button>
            </DialogActions>
          </Form>
        )}
      </Formik>


    </Dialog>
  )
}

NewProjectDialog.propTypes = {
  onSubmit: PropTypes.func.isRequired,
  open: PropTypes.bool.isRequired,
  onRequestClose: PropTypes.func.isRequired
}

export default NewProjectDialog
Share Improve this question asked Apr 19, 2020 at 3:04 Hiroaki MachidaHiroaki Machida 1,0902 gold badges12 silver badges23 bronze badges 3
  • do you want to set the default value or when should the value be changed? – fayeed Commented Apr 19, 2020 at 3:56
  • I want to change the value of #quaggaIsbn when I chose a file and that is loaded to #quaggaFile. (it is reflected to the view but not the form information, when I submit the form, it is not sent to the server.) – Hiroaki Machida Commented Apr 19, 2020 at 6:29
  • When I upload a file, inputFile() is called. That calls analyzeQuaggaFile() and analyzeQuaggaFile() tries to change the form value #quaggaIsbn, but it seems it doesn't because the value of #quaggaIsbn is not included in the data submitted. – Hiroaki Machida Commented Apr 19, 2020 at 6:33
Add a ment  | 

3 Answers 3

Reset to default 5

It is possible to make the entire Formik to reset once its properties get updated outside its context with enableReinitialize property.

https://formik/docs/api/formik#enablereinitialize-boolean

Like this:

<Formik validationSchema={validationSchema} initialValues={this.state.formValues} onSubmit={this.handleFormSubmission} enableReinitialize={true}>

Formik render method provides a prop to change the field value manually using setFieldValue prop it takes the field name & new values as parameters you can read about if more from here

As for what you need to change is here

// accept a new parameter which you can pass to the `analyzeQuaggaFile` function
function inputFile(setFieldValue) {
  const file = document.getElementById("quaggaFile").files[0];

  const reader = new FileReader();

  reader.addEventListener(
    "load",
    function () {
      // pass the setFieldValue
      analyzeQuaggaFile(reader.result, setFieldValue);
    },
    false
  );

  reader.readAsDataURL(file);
}

// second parameter is setFieldValue
function analyzeQuaggaFile(src, setFieldValue) {
  Quagga.decodeSingle(
    {
      src: src,
      numOfWorkers: 0,
      inputStream: {
        size: 800,
      },
      decoder: {
        readers: ["ean_reader"],
      },
    },
    function (result) {
      if (result.codeResult) {
        // update the isbn field value
        setFieldValue("isbn", result.codeResult.code);
      } else {
        console.log("not detected");
      }
    }
  );
}

Now change this in your JSX code:

<Formik initialValues={{ name: "" }} onSubmit={handleSubmit}>
  {({ errors, isSubmitting, setFieldValue }) => (
    <Form className={classes.root}>
      {/* Other fields */}
      Scan bar code:
      <input
        id="quaggaFile"
        type="file"
        accept="image/*"
        capture="camera"
        onChange={() => inputFile(setFieldValue)} // pass the setFieldValue property from formik 
      />
      {/* Other fields */}
    </Form>
  )}
</Formik>;

    import {
      useFormik
    } from "formik";
    import * as yup from 'yup';

    export default function ChangeFormikValueOutsideForm() {
      const initialValues = {
        first_name: 'John',
        last_name: 'Doe'
      }
      const validationSchema = yup.object({
        first_name: yup.string("must be a string")
          .required("Must have a first name"),
        last_name: yup.string("must be a string")
      })
      const formik = useFormik({
          initialValues,
          validationSchema,
          onSubmit: (values) => {}
        )
      }
    }

    let handleLastNameChange = () => {
      formik.setFieldValue('last_name', Math.ceil(Math.random() * 100))
    }

    return (
    <form onSubmit = {
        formik.handleSubmit
      } >
      <p> First Name * </p> 
      <input
        name = "first_name"
        id = "first_name"
        type = "text"
        onChange = {
          formik.handleChange
        }
        value = {
          formik.values.first_name
        }
      />
      <p> Last Name </p>
      <input
        name = "last_name"
        id = "last_name"
        type = "text"
        onChange = {
          handleLastNameChange
        }
        value = {
          formik.values.last_name
        }
      />
      <input
        type = "submit"
        value = "Submit Form"
      />
      </form>
      )
    }

It works with the useFormik hook this permits you to define the form outside of a formik tag and then benefit from the formik variable to execute the setFieldValue method out of a form. infact, you are handling the form entirely out of the form ;)

Same idea for using with material ui too. it works

发布评论

评论列表(0)

  1. 暂无评论