如何从 From 外部更改 Formik TextField 值?
How do I change a Formik TextField value from the outside of the From?
在模块对话框中,我想更改输入值 (#quaggaIsbn) 的值。我试过 document.getElementById("quaggaIsbn").value = result.codeResult.code
但它没有反映到表单发送到服务器的值中。如何更改 Formik 发送到服务器的值?
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"
component={TextField}
margin="normal"
fullWidth
/>
Scan bar code:<input id="quaggaFile" type="file" accept="image/*" capture="camera" onChange={inputFile}/>
<Field
name="title"
label="Title"
component={TextField}
margin="normal"
fullWidth
/>
<Field
name="status"
label="Status"
component={TextField}
margin="normal"
fullWidth
/>
<Field
name="price"
label="Price"
component={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
Formik render 方法提供了一个使用 setFieldValue
prop 手动更改字段值的 prop,它将字段名称和新值作为参数,您可以从 here[=14= 中了解更多信息]
至于你要改的就在这里
// 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");
}
}
);
}
现在在您的 JSX 代码中更改它:
<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>;
使用 enableReinitialize 属性。
可以在其属性在其上下文之外更新后重置整个 Formik。
https://formik.org/docs/api/formik#enablereinitialize-boolean
像这样:
<Formik validationSchema={validationSchema} initialValues={this.state.formValues} onSubmit={this.handleFormSubmission} enableReinitialize={true}>
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>
)
}
它与 useFormik 挂钩一起使用,这允许您在 formik 标记之外定义表单,然后利用 formik 变量从表单中执行 setFieldValue 方法。事实上,您处理的表格完全不符合表格 ;)
与 material ui 一起使用的想法相同。有效
在模块对话框中,我想更改输入值 (#quaggaIsbn) 的值。我试过 document.getElementById("quaggaIsbn").value = result.codeResult.code
但它没有反映到表单发送到服务器的值中。如何更改 Formik 发送到服务器的值?
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"
component={TextField}
margin="normal"
fullWidth
/>
Scan bar code:<input id="quaggaFile" type="file" accept="image/*" capture="camera" onChange={inputFile}/>
<Field
name="title"
label="Title"
component={TextField}
margin="normal"
fullWidth
/>
<Field
name="status"
label="Status"
component={TextField}
margin="normal"
fullWidth
/>
<Field
name="price"
label="Price"
component={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
Formik render 方法提供了一个使用 setFieldValue
prop 手动更改字段值的 prop,它将字段名称和新值作为参数,您可以从 here[=14= 中了解更多信息]
至于你要改的就在这里
// 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");
}
}
);
}
现在在您的 JSX 代码中更改它:
<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>;
使用 enableReinitialize 属性。
可以在其属性在其上下文之外更新后重置整个 Formik。https://formik.org/docs/api/formik#enablereinitialize-boolean
像这样:
<Formik validationSchema={validationSchema} initialValues={this.state.formValues} onSubmit={this.handleFormSubmission} enableReinitialize={true}>
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>
)
}
它与 useFormik 挂钩一起使用,这允许您在 formik 标记之外定义表单,然后利用 formik 变量从表单中执行 setFieldValue 方法。事实上,您处理的表格完全不符合表格 ;)
与 material ui 一起使用的想法相同。有效