首页 > 解决方案 > 有没有办法在提交时更改表单值

问题描述

我有一种情况,我想将两个按钮用作提交。

我怎样才能使邮政编码的值(在formik中)与选项的值(按钮onclick)相结合,例如{“option”:“adult”,“zip_code”:“00000”}

我发现了这个:https ://github.com/formium/formik/issues/467#issuecomment-369833667

但它是针对类组件的,并没有显示如何将按钮值转换为 formik 值......

import React, { useState, useEffect } from 'react';
import { Form, Formik, useField } from 'formik';
import * as Yup from 'yup';


const FORM_INPUT_BOX = "m-2 border border-gray-300 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:ring-yellow-500 focus:border-transparent"
const FORM_INPUT_LABEL = "ml-2 text-gray-700"
const FORM_INPUT_ERROR = "break-normal relative bottom-2 left-2 text-sm text-red-500"
const FORM_DROPDOWN = "m-2 focus:ring-yellow-500 border border-gray-300 focus:border-yellow-500 h-full border-transparent bg-transparent text-gray-500 sm:text-sm rounded"
export const FORM_BUTTON = "ml-2 mr-2 py-1 border border-transparent text-medium rounded-md text-white bg-gray-600 hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500"

const CustomTextInput = ({ label, ...props }) => {
    const [field, meta] =useField(props); //using the hook useField, and destructuring
    return(
        <> {/*so we don't return any div tags - its just a react fragment */}
        <label htmlFor={props.id || props.name} className={FORM_INPUT_LABEL}> {label} </label>
        <input className={FORM_INPUT_BOX}{...field}{...props} />
        {meta.touched && meta.error ? (
            <div className={FORM_INPUT_ERROR}>{meta.error}</div>
        ) : null}
        </>
    )
}

const ButtonMaker = (props) => {
    const {mainprops,userprops,adoptprops,...optionprops} = props
    return(
        <>
        <button className={FORM_BUTTON} id={optionprops.id} onClick={()=>{optionprops.setButtonClick(true);
                                                                          optionprops.setOption(optionprops.id)}}
        >{optionprops.label}</button>
        </>
    )
};

export default function RegistrationForm(props) {

    const {mainprops,userprops,...adoptprops} = props;
    const [buttonClick, setButtonClick] = useState(false);
    const [option, setOption] = useState('')
    const allprops = {
        mainprops,
        userprops,
        adoptprops,
        buttonClick,
        setButtonClick,
        setOption
    };

    useEffect(()=>{
        if (buttonClick){
        alert(option)};
        
    },[buttonClick])


    // https://regex101.com/ 
    const zipRegExp= /^([0-9]{5})$/;
    //zipRegExp: only 5 digits
    const zipRegExp_plus4= /^([0-9]{5})(?:[-\s]*([0-9]{4}))?$/;

    return (
        <Formik
            initialValues={{
                zip_code       :   ''
            }}
            validationSchema={Yup.object({
                zip_code: Yup.string()
                    .min(5,'five digits needed')
                    .matches(zipRegExp, 'invalid zipcode')
                    .required('required field'),
            })}
            onSubmit={ (values, { setSubmitting, resetForm }) => {
                setTimeout(() => {
                    // alert(JSON.stringify(values, null, 2));
                    resetForm();
                    setSubmitting(false);
            }, 1000)
            }}
        >
            {props => (
                <Form className='bg-white rounded px-8 py-8 mt-4 mb-4'>
                    <div className='flex justify-center align-center'>
                    <section className='m-2 w-52 flex flex-col border'>
                        <CustomTextInput label='Enter ZIP Code' name='zip_code' placeholder='zipcode' />
                    </section>
                    </div>
                    <br></br>
                    <div className='flex justify-center align-center'>
                    <ButtonMaker {...allprops} groupa='pet' groupb='adopt' id='adult' label='adult'/>
                    <ButtonMaker {...allprops} groupa='pet' groupb='adopt' id='puppy' label='puppy'/>
                    </div>
                </Form>
            )}
        </Formik>
    )
}

我尝试过的其他东西:

将此添加到每个按钮:formkprops={props}

这对于点击功能的按钮制造商:formkprops.submitForm()

但它不起作用。

标签: javascriptreactjsformik

解决方案


尝试以下操作:

import React, { useState, useEffect } from 'react';
import { Form, Formik, useField } from 'formik';
import * as Yup from 'yup';


const FORM_INPUT_BOX = "m-2 border border-gray-300 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:ring-yellow-500 focus:border-transparent"
const FORM_INPUT_LABEL = "ml-2 text-gray-700"
const FORM_INPUT_ERROR = "break-normal relative bottom-2 left-2 text-sm text-red-500"
const FORM_DROPDOWN = "m-2 focus:ring-yellow-500 border border-gray-300 focus:border-yellow-500 h-full border-transparent bg-transparent text-gray-500 sm:text-sm rounded"
export const FORM_BUTTON = "ml-2 mr-2 py-1 border border-transparent text-medium rounded-md text-white bg-gray-600 hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500"

const CustomTextInput = ({ label, ...props }) => {
    const [field, meta] =useField(props); //using the hook useField, and destructuring
    return(
        <> {/*so we don't return any div tags - its just a react fragment */}
        <label htmlFor={props.id || props.name} className={FORM_INPUT_LABEL}> {label} </label>
        <input className={FORM_INPUT_BOX}{...field}{...props} />
        {meta.touched && meta.error ? (
            <div className={FORM_INPUT_ERROR}>{meta.error}</div>
        ) : null}
        </>
    )
}

const ButtonMaker = (props) => {
    const {mainprops,userprops,adoptprops,...optionprops} = props
    return(
        <>
        <button className={FORM_BUTTON} id={optionprops.id} onClick={()=>{optionprops.setButtonClick(true);
                                                                          optionprops.setOption({"option": optionprops.id, "zipcode": optionprops.zip_code})}}
        >{optionprops.label}</button>
        </>
    )
};

export default function RegistrationForm(props) {

    const {mainprops,userprops,...adoptprops} = props;
    const [buttonClick, setButtonClick] = useState(false);
    const [option, setOption] = useState(null)
    const allprops = {
        mainprops,
        userprops,
        adoptprops,
        buttonClick,
        setButtonClick,
        setOption
    };

    useEffect(()=>{
        if (buttonClick){
        alert(JSON.stringify(option, null, 4))};
        
    },[buttonClick])


    // https://regex101.com/ 
    const zipRegExp= /^([0-9]{5})$/;
    //zipRegExp: only 5 digits
    const zipRegExp_plus4= /^([0-9]{5})(?:[-\s]*([0-9]{4}))?$/;

    return (
        <Formik
            initialValues={{
                zip_code       :   ''
            }}
            validationSchema={Yup.object({
                zip_code: Yup.string()
                    .min(5,'five digits needed')
                    .matches(zipRegExp, 'invalid zipcode')
                    .required('required field'),
            })}
            onSubmit={ (values, { setSubmitting, resetForm }) => {
                setTimeout(() => {
                    // alert(JSON.stringify(values, null, 2));
                    resetForm();
                    setSubmitting(false);
            }, 1000)
            }}
        >
            {props => (
                <Form className='bg-white rounded px-8 py-8 mt-4 mb-4'>
                    <div className='flex justify-center align-center'>
                    <section className='m-2 w-52 flex flex-col border'>
                        <CustomTextInput label='Enter ZIP Code' name='zip_code' placeholder='zipcode' />
                    </section>
                    </div>
                    <br></br>
                    <div className='flex justify-center align-center'>
                    <ButtonMaker {...allprops} groupa='pet' groupb='adopt' id='adult' label='adult' zip_code={props.values.zip_code}/>
                    <ButtonMaker {...allprops} groupa='pet' groupb='adopt' id='puppy' label='puppy' zip_code={props.values.zip_code}/>
                    </div>
                </Form>
            )}
        </Formik>
    )
}

当调用 actionprops 的 setoption 函数时,您需要创建一个选项属性并添加一个 zip_code 属性。为了在警报中显示它,您需要使用 JSON.stringify 函数来显示使用警报函数的选项。

**原始海报评论部分要求信息的解决方案**

您可以为您的应用程序创建状态管理或使用类似 Redux 的库。在状态管理中,您可以拥有一组与上面创建的对象类似的对象。然后,您可以让任何想要访问此数组的组件。您还需要为用户提供最终提交,以表明他们何时完成,或者用户在继续之前必须选择的所需选项数量。

参考:

堆栈溢出。如何警告 javascript 对象。https://stackoverflow.com/a/64941710/8121551。(2021 年 10 月 10 日访问)。


推荐阅读