admin管理员组

文章数量:1401651

I tried to implement something like a multi-select, where the user can either select a value from a data list or can type in a new value. A chosen value should be added to an array if the user presses enter. For detecting changes in the input field I use onChange and a state variable that saves the current value typed in. For detecting the press of enter I use onKeyDown. The problem is that I'm no longer able to type something in the input field, however choosing values from the data list works. I figured out that when I ment out onKeyDown, I can type something in the input field and can also choose from values provided by the data list. However, in this case, adding values to an array on the press of enter doesn't work. I'm fairly new to React, is there something I miss? My current code looks like follows:

const EditableMultiSelect = ({ field, helpers, metadataField, editMode, setEditMode }) => {
    const { t } = useTranslation();

    const [inputValue, setInputValue] = useState('');

    const handleChange = e => {
       
        const itemValue = e.target.value;
        setInputValue(itemValue);


    }

    const handleKeyDown = event => {
        event.preventDefault();

        if (event.keyCode === 13) {
            field.value[field.value.length] = inputValue;
            helpers.setValue(field.value);
            setInputValue("");
        }


    }

    const removeItem = () => {
        console.log('to be implemented');
    }

    return (
        editMode ? (
            <>
                <div
                     onBlur={() => setEditMode(false)}
                     ref={childRef}>
                    <input name="inputValue"
                           value={inputValue}
                           type="text"
                           onKeyDown={e => handleKeyDown(e)}
                           onChange={e => handleChange(e)}
                           placeholder={t('EDITABLE.MULTI.PLACEHOLDER')}
                           list="data-list"
                    />
                    <datalist id="data-list">
                        {metadataField.collection.map((item, key) => (
                            <option key={key}>{t(item.value)}</option>
                        ))}
                    </datalist>
                </div>
                {(field.value instanceof Array && field.value.length !== 0) ? (field.value.map((item, key) => (
                        <span className="ng-multi-value"
                              key={key}>
                        {t(item)}
                            <a onClick={() => removeItem(key)}>
                            <i className="fa fa-times" />
                        </a>
                    </span>
                    ))) : null}
            </>

        ) : (
            <div onClick={() => setEditMode(true)}>
                {(field.value instanceof Array && field.value.length !== 0) ? (
                    <ul>
                        {field.value.map((item, key) => (
                            <li key={key}>
                                <span>{item}</span>
                            </li>
                        ))}
                    </ul>
                ) : (
                    <span className="editable preserve-newlines">
                            {""}
                    </span>
                )}
                <i className="edit fa fa-pencil-square"/>
            </div>
        )
    );
};

I tried to implement something like a multi-select, where the user can either select a value from a data list or can type in a new value. A chosen value should be added to an array if the user presses enter. For detecting changes in the input field I use onChange and a state variable that saves the current value typed in. For detecting the press of enter I use onKeyDown. The problem is that I'm no longer able to type something in the input field, however choosing values from the data list works. I figured out that when I ment out onKeyDown, I can type something in the input field and can also choose from values provided by the data list. However, in this case, adding values to an array on the press of enter doesn't work. I'm fairly new to React, is there something I miss? My current code looks like follows:

const EditableMultiSelect = ({ field, helpers, metadataField, editMode, setEditMode }) => {
    const { t } = useTranslation();

    const [inputValue, setInputValue] = useState('');

    const handleChange = e => {
       
        const itemValue = e.target.value;
        setInputValue(itemValue);


    }

    const handleKeyDown = event => {
        event.preventDefault();

        if (event.keyCode === 13) {
            field.value[field.value.length] = inputValue;
            helpers.setValue(field.value);
            setInputValue("");
        }


    }

    const removeItem = () => {
        console.log('to be implemented');
    }

    return (
        editMode ? (
            <>
                <div
                     onBlur={() => setEditMode(false)}
                     ref={childRef}>
                    <input name="inputValue"
                           value={inputValue}
                           type="text"
                           onKeyDown={e => handleKeyDown(e)}
                           onChange={e => handleChange(e)}
                           placeholder={t('EDITABLE.MULTI.PLACEHOLDER')}
                           list="data-list"
                    />
                    <datalist id="data-list">
                        {metadataField.collection.map((item, key) => (
                            <option key={key}>{t(item.value)}</option>
                        ))}
                    </datalist>
                </div>
                {(field.value instanceof Array && field.value.length !== 0) ? (field.value.map((item, key) => (
                        <span className="ng-multi-value"
                              key={key}>
                        {t(item)}
                            <a onClick={() => removeItem(key)}>
                            <i className="fa fa-times" />
                        </a>
                    </span>
                    ))) : null}
            </>

        ) : (
            <div onClick={() => setEditMode(true)}>
                {(field.value instanceof Array && field.value.length !== 0) ? (
                    <ul>
                        {field.value.map((item, key) => (
                            <li key={key}>
                                <span>{item}</span>
                            </li>
                        ))}
                    </ul>
                ) : (
                    <span className="editable preserve-newlines">
                            {""}
                    </span>
                )}
                <i className="edit fa fa-pencil-square"/>
            </div>
        )
    );
};
Share Improve this question asked Nov 26, 2020 at 8:39 izzykuizzyku 631 silver badge5 bronze badges 1
  • In handling handleKeyDown you're calling event.preventDefault();, which will effectively prevent the keypress from doing anything. – user5734311 Commented Nov 26, 2020 at 8:47
Add a ment  | 

3 Answers 3

Reset to default 6

You're calling event.preventDefault() every time a key is pressed. You should move it inside the if statement:

const handleKeyDown = event => {
  if (event.keyCode === 13) {
    event.preventDefault();
    field.value[field.value.length] = inputValue;
    helpers.setValue(field.value);
    setInputValue("");
  }
}

you can't type anything anymore in the input text because in the handleKeyDown event handler, you're calling event.preventDefault() in the early lines. So i think you just have to move it into the if case:

const handleKeyDown = event => {
  if (event.keyCode === 13) {
    event.preventDefault();

    field.value[field.value.length] = inputValue;
    helpers.setValue(field.value);
    setInputValue("");
  }
}

Remove e.preventDefault() or put it inside the if statements.
It is the one preventing the input from being editable.

本文标签: javascriptReactInput not working when using onChange and onKeyDownStack Overflow