Автозаполнение с понижением при сбросе значения onBlur с помощью Formik - PullRequest
1 голос
/ 06 марта 2019

У меня есть форма с полем, которое должно показывать предложения через вызов API.Пользователю должно быть разрешено выбирать один из этих параметров или нет, и это значение, которое они вводят, используется для отправки с формой, но это поле является обязательным.Я использую Formik для обработки формы, Yup для проверки формы, чтобы проверить, является ли это поле обязательным, пониженную передачу для автозаполнения и Material-UI для поля.

Проблема возникает, когда пользователь решает неиспользуйте один из предложенных вариантов и триггеры onBlur.OnBlur всегда сбрасывает поле, и я полагаю, что это вызвано понижением, но решения этой проблемы предлагают контролировать состояние пониженной передачи, и когда я пытаюсь, это не работает с Formik и Yup, и есть некоторые проблемы, которые я могуне совсем понимаю, так как эти компоненты управляют значением inputValue этого поля.

Вот что у меня есть:

const AddBuildingForm = props => {
    const [suggestions, setSuggestions] = useState([]);
    const { values,
        errors,
        touched,
        handleChange,
        handleBlur,
        handleSubmit, 
        modalLoading,
        setFieldValue,
        setFieldTouched,
        classes } = props;

    const loadOptions = (inputValue) => {  
        if(inputValue && inputValue.length >= 3 && inputValue.trim() !== "")
        {
            console.log('send api request', inputValue)
            LocationsAPI.autoComplete(inputValue).then(response =>  {
                let options = response.data.map(erlTO => { 
                    return {
                        label: erlTO.address.normalizedAddress,
                        value: erlTO.address.normalizedAddress
                    }
                });
                setSuggestions(options);
            });
        }
        setFieldValue('address', inputValue); // update formik address value
    }

    const handleSelectChange = (selectedItem) => {
        setFieldValue('address', selectedItem.value); // update formik address value
    }

    const handleOnBlur = (e) => {
        e.preventDefault();
        setFieldValue('address', e.target.value);
        setFieldTouched('address', true, true);
    }

    const handleStateChange = changes => {
        if (changes.hasOwnProperty('selectedItem')) {
            setFieldValue('address', changes.selectedItem)
          } else if (changes.hasOwnProperty('inputValue')) {
            setFieldValue('address', changes.inputValue);
          }
    }

    return (
        <form onSubmit={handleSubmit} autoComplete="off">
            {modalLoading && <LinearProgress/>}
            <TextField
                id="name"
                label="*Name"
                margin="normal"
                name="name"
                type="name"
                onChange={handleChange}
                value={values.name}
                onBlur={handleBlur}
                disabled={modalLoading}
                fullWidth={true}
                error={touched.name && Boolean(errors.name)}
                helperText={touched.name ? errors.name : ""}/> 
            <br/>
            <Downshift  id="address-autocomplete"
                onInputValueChange={loadOptions}
                onChange={handleSelectChange}
                itemToString={item => item ? item.value : '' }
                onStateChange={handleStateChange}
               >
                {({
                        getInputProps,
                        getItemProps,
                        getMenuProps,
                        highlightedIndex,
                        inputValue,
                        isOpen,
                    }) => (
                        <div>
                            <TextField
                                id="address"
                                label="*Address"
                                name="address"
                                type="address"
                                className={classes.autoCompleteOptions}
                                {...getInputProps( {onBlur: handleOnBlur})}
                                disabled={modalLoading}
                                error={touched.address && Boolean(errors.address)}
                                helperText={touched.address ? errors.address : ""}/>
                            <div {...getMenuProps()}>
                                {isOpen ? (
                                    <Paper className={classes.paper} square>
                                        {suggestions.map((suggestion, index) =>
                                            <MenuItem {...getItemProps({item:suggestion, index, key:suggestion.label})} component="div"  >
                                                {suggestion.value}
                                            </MenuItem>
                                        )}
                                    </Paper>
                                ) : null}
                            </div>
                        </div>
                )}                
            </Downshift>

            <Grid container direction="column" justify="center" alignItems="center">
                <Button id="saveBtn"
                        type="submit" 
                        disabled={modalLoading} 
                        className = {classes.btn}
                        color="primary" 
                        variant="contained">Save</Button>
            </Grid>
        </form>
    );
}

const AddBuildingModal = props => {
    const { modalLoading, classes, autoComplete, autoCompleteOptions } = props;
    return(
        <Formik
            initialValues={{ 
                name: '', 
                address: '',
            }}
            validationSchema={validationSchema}
            onSubmit = {
                (values) => {
                    values.parentId = props.companyId;
                    props.submitAddBuildingForm(values);
                }
            }
            render={formikProps => <AddBuildingForm 
                                        autoCompleteOptions={autoCompleteOptions}
                                        autoComplete={autoComplete} 
                                        classes={classes} 
                                        modalLoading={modalLoading}
                                        {...formikProps} />}
        />
    );
}

1 Ответ

2 голосов
/ 13 марта 2019

Получил это на работу. Необходимо использовать handleOuterClick и установить состояние пониженной передачи со значением Formik:

const handleOuterClick = (state) => {
    // Set downshift state to the updated formik value from handleOnBlur
    state.setState({
        inputValue: values.address
    })
}

Теперь значение остается в поле ввода всякий раз, когда я щелкаю.

...