I have a form made that I want to try and control the input elements from outside of the form framework. In this situation I am still using old class components
<form id="myform">
<input type="text" name="foo" />
</form>
This code works if its inside a functional component Formik external controlling of inputs
https://l6mssp.csb.app/ and run this code in the console:
window.dispatchEvent(
new CustomEvent("formik_external_change", {
detail: [
{ name: "wound_opening", value: ['0'] },
{ name: "pain_level", value: 4 },
{ name: "healthy_regrowth_of_skin", value: ['0'] },
{ name: "discolouration", value: 3 },
{ name: "swelling", value: 2 },
{ name: "describe_your_symptoms_here", value: "Feeling dizzy" }
]
})
);
https://codesandbox.io/s/nameless-framework-l6mssp
GeneralFormik.js
add the marked line (around line 129):
return (
<div id={this.props.schema.id} className={"general-formik standard-padding " + getFormType()}>
<Formik
initialValues={getInitialValues(this.props.schema.initialValues, this.props.schema.fields)}
validationSchema={createYupSchema(this.props.schema.fields)}
onSubmit={this.submitMyForm}
innerRef={this.visitFormRef}
>
{(props) => {
if (this.props.externalControlRef) {
this.props.externalControlRef.current = props.setFieldValue; // assigning the method to the external ref
}
return (
<Form id={this.props.id} onKeyDown={this.onKeyDown}>
<FieldMaker schema={this.props.schema} values={props.values} fieldChanged={this.fieldChanged} onErrorHandle={this.onErrorHandle} />
<ButtonMaker schema={this.props.schema} />
</Form>
)
}
}
</Formik>
</div>
)
}
App.js
After declaring the schema:
// Creating the ref
const externalControlRef = useRef();
// Creating a function to be able to call it with a nice name
const setFormValues = (jsonArray) => {
jsonArray.forEach(field => externalControlRef.current(field.name, field.value))
}
// Global listener for the custom event "formik_external_change"
useEffect(() => {
const handleExternalFormikChange = (e) => {
setFormValues(e.detail);
}
window.addEventListener("formik_external_change", handleExternalFormikChange);
// Need to remove the event listener on component unload otherwise it would have multiple events
return () => window.removeEventListener("formik_external_change", handleExternalFormikChange);
}, [])
// Triggering with a button but the code inside this can be called from anywhere (console or the text to speech library for example)
const handleChange = () => {
window.dispatchEvent(
new CustomEvent("formik_external_change", {
detail: [
{ name: "wound_opening", value: ['0'] },
{ name: "pain_level", value: 4 },
{ name: "healthy_regrowth_of_skin", value: ['0'] },
{ name: "discolouration", value: 3 },
{ name: "swelling", value: 2 },
{ name: "describe_your_symptoms_here", value: "Feeling dizzy" }
]
})
);
}
return (
<div className="App">
{/* // Click to change! */}
<button onClick={handleChange}>Check skin and change pain </button>
<GeneralFormik
externalControlRef={externalControlRef} // Passing the ref down
schema={schema3}
submitHandler={function (data) {
console.log("new data in parent", data);
}}
/>
</div>
);
http://jsfiddle.net/3bsdn8yz/1/
<div id="myform3" class="general-formik standard-padding ">
<form action="#">
<div class="field field-comment">
<div class="MuiFormControl-root MuiFormControl-fullWidth MuiTextField-root css-wb57ya-MuiFormControl-root-MuiTextField-root">
<label class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-colorPrimary Mui-error MuiFormLabel-filled MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined css-1sumxir-MuiFormLabel-root-MuiInputLabel-root" data-shrink="true" for="mui-59" id="mui-59-label">Describe your symptoms here</label>
<div class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-colorPrimary Mui-error MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-multiline css-8ewcdo-MuiInputBase-root-MuiOutlinedInput-root">
<textarea rows="6" aria-invalid="true" autocomplete="off" name="describe_your_symptoms_here" placeholder="Text field" maxlength="700" class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputMultiline css-1sqnrkk-MuiInputBase-input-MuiOutlinedInput-input" id="mui-59" style="height: 138px;">xxx</textarea>
<textarea aria-hidden="true" class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputMultiline css-1sqnrkk-MuiInputBase-input-MuiOutlinedInput-input" readonly="" tabindex="-1" style="visibility: hidden; position: absolute; overflow: hidden; height: 0px; top: 0px; left: 0px; transform: translateZ(0px); padding: 0px; width: 1115px;"></textarea>
<fieldset aria-hidden="true" class="MuiOutlinedInput-notchedOutline css-1d3z3hw-MuiOutlinedInput-notchedOutline">
<legend class="css-14lo706"><span>Describe your symptoms here</span></legend>
</fieldset>
</div>
</div>
<p class="MuiFormHelperText-root Mui-error css-1d1r5q-MuiFormHelperText-root">Must be at least 8 characters</p>
</div>
<div class="button-wrapper"><button class="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeMedium MuiButton-containedSizeMedium MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeMedium MuiButton-containedSizeMedium css-sghohy-MuiButtonBase-root-MuiButton-root" tabindex="0" type="reset">Reset<span class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"></span></button><button class="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedSecondary MuiButton-sizeMedium MuiButton-containedSizeMedium MuiButton-root MuiButton-contained MuiButton-containedSecondary MuiButton-sizeMedium MuiButton-containedSizeMedium css-zcbmsk-MuiButtonBase-root-MuiButton-root" tabindex="0" type="submit">Submit<span class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"></span></button></div>
</form>
</div>
9th June 2023 I managed to get the value to change - but it reverted back to the formik object.
document.getElementsByName("describe_your_symptoms_here")[0].value = "Roger Rabbit"
How to update Formik Field from external actions
other research
How do I change a Formik TextField value from the outside of the From?
- I think he creates a function outside the framework and feeds it into formik at a particular place.
"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>;
https://github.com/jaredpalmer/formik/issues/229 How to update Formik Field from external actions