如何为“反应选择”实施字段验证

时间:2018-08-21 14:50:18

标签: react-select

我需要对“反应选择”(github repo)进行简单的“必需”验证。 在最新版本中,它使用css-in-js方法。所以我有自定义样式:

export const customStyles = {


 control: (base, state) => ({
        ...base,
    }),

    menu: (base, state) => ({
        ...base,
    }),

    menuList: (base, state) => ({
        ...base,
    }),
}

如何更改例如borderColor如果字段无效?

6 个答案:

答案 0 :(得分:4)

关于这一点,GitHub上存在一个问题。

我看到两种不同的方法:

  1. “懒惰”的,您可以通过添加特定的className来更改边框颜色。 Example here
  2. 当您要自定义原始选择时,我建议将customSelect嵌入一个单独的文件中。然后,您可以传递道具isValid并使用它来更改您的borderColor

class CustomSelect extends React.Component {
  render() {
    const {
      isValid
    } = this.props
    
    const customStyles = {
      control: (base, state) => ({
        ...base,
        // state.isFocused can display different borderColor if you need it
        borderColor: state.isFocused ?
          '#ddd' : isValid ?
          '#ddd' : 'red',
        // overwrittes hover style
        '&:hover': {
          borderColor: state.isFocused ?
            '#ddd' : isValid ?
            '#ddd' : 'red'
        }
      })
    }
    return <Select styles={ customStyles } {...this.props}/>
  }
}

答案 1 :(得分:2)

某人不想一直在condition = "filter(event.name)"中为此要求的验证添加代码的人的帮助。只需使用react-hook-form-input

react-select

<RHFInput as={<Select options={options} />} rules={{ required: 'Please select an option'}} name="reactSelect" register={register} setValue={setValue} /> 中的RHFInput对我来说只是一个保存。完整的示例-react-hook-form-input

react-hook-form-input

希望,它将帮助像我这样的初学者做出反应。

答案 2 :(得分:0)

render.js

export const renderSelect = (props) => (
<div>
    <Select
    {...props}
    value={props.input.value}
    onChange={(value) => props.input.onChange(value)}
    onBlur={() => props.input.onBlur(props.input.value)}
    options={props.options}
    key={props.input.value}
    />
    {props.meta.touched && (props.meta.error && <p  style={{ color: "red",fontSize:"12px" }}>{props.meta.error}</p>)}
</div>

);

implementForm.js

<Field 
                name="sex" 
                component={renderSelect} 
                options={Status}
                isClearable={true}
                validate={required}
              />

requiredFileMessage.js

const required = value => value ? undefined : 'Required'

答案 3 :(得分:0)

我发现的最好方法是创建一个透明输入字段,该字段将通过javascript标准checkValidity进行查询。这应该具有绝对的位置以及100%的宽度和高度。然后,您可以将侦听器绑定到checkValidity创建的无效事件的输入字段

这是我使用的代码。对于值字段的使用以及某些样式(对于MDB输入)有一些更改,但是您可以更改输入的类别以匹配您自己的样式库。这样,您的验证样式将与您现有的表单输入相同。

希望这对某人有帮助。

    /**************************************************************************************
 *** Select - New Select Control Using react-select (to stop stupid probs with MDB) ***
 **************************************************************************************/
// Use This progressively instead of InputSelect
/* Differences from native ReactSelect 
    Validation - Applies transparent input overlay that works with form checkValidity()
    value: This is the record.field value not an object {label: x, value: y} as for react-select
    grouped: Explicitly set grouped options when set true
    objValue: Works the same as react-select value object
*/
// Note: value property works differently do react-select , use ObjValue to work same as react-select
export const Select = (props) => {
  let { id, options, cols, value, objValue, label, grouped, ...o } = props
  id = id ? id : 'react-select'
  const [selected, setSelected] = useState(value)
  const [invalid, setInvalid] = useState(false)

  //DEFAULTS
  if (!grouped) grouped = false

  //--------------------------
  // VALIDATION EVENT HANDLERS
  //--------------------------
  useEffect(() => {
    //ADD EVENT HANDLER FOR FOR VALIDATION
    let ele = document.getElementById(`${id}_invalid}`)
    ele.addEventListener('invalid', (e) => {
      console.log('e is ', selected, e)
      if (typeof selected === 'undefined' || selected !== null) setInvalid(true)
    })
    //ON COMPONENT EXIT - REMOVE EVENT HANDLER
    return () => {
      ele.removeEventListener('invalid', () => {
        setInvalid(false)
      })
    }
    // eslint-disable-next-line
  }, [])

  //Value property (Allows Single field assignent) - translates to object in for {label:x, value:y}
  useEffect(() => {
    let val
    if (grouped) {
      val = _.findInGroup(options, 'options', (rec) => rec.value === value)
    } else {
      val = options.find((rec) => rec.value === value)
    }
    //console.log('Selected==>', val)
    setSelected(val)
    // eslint-disable-next-line
  }, [value, options])

  //objValue Property (Emulate standard react-select value object)
  useEffect(() => {
    if (objValue) {
      setSelected(objValue)
    }
    // eslint-disable-next-line
  }, [objValue])

  //STYLING SAME AS MDB INPUT COMPONENTS
  const customStyles = {
    valueContainer: (provided, state) => ({
      ...provided,
      backgroundColor: 'aliceblue',
    }),
    dropdownIndicator: (provided, state) => ({
      ...provided,
      backgroundColor: 'aliceblue',
    }),
  }

  const handleChange = (opt, i) => {
    setSelected(opt)
    //Callback function (i is used for nested data in record)
    if (props && props.onChange) props.onChange(opt, i)
  }

  return (
    <Col cols={cols}>
      {label && <label className='tp-label text-uppercase'>{label}</label>}
      <div className='select-wrapper'>
        <ReactSelect
          styles={customStyles}
          value={selected ? selected : ''}
          options={options}
          onChange={(val, i) => handleChange(val, i)}
          isSearchable={true}
          {...o}
        />
        <input
          id={`${id}_invalid}`}
          name={`${id}_invalid}`}
          value={selected ? selected : ''}
          onChange={() => {}}
          tabIndex={-1}
          className={`form-control tp-input w-100 ${invalid ? '' : 'd-none'}`}
          autoComplete='off'
          //value={selected}
          onFocus={() => {
            setInvalid(false)
          }}
          style={{
            position: 'absolute',
            color: 'transparent',
            backgroundColor: 'transparent',
            top: 0,
            left: 0,
            width: '100%',
            height: '100%',
            zIndex: 0,
          }}
          required={true}
        />
      </div>
    </Col>
  )
}

答案 4 :(得分:0)

看这个链接:https://codesandbox.io/s/react-hook-form-controller-079xx?file=/src/index.js

你必须使用控制器

   <Controller
          control={control}
          rules={{ required: true }}
          name="citySelect"
          getOptionLabel={(option) => option.name}
          getOptionValue={(option) => option.id}
          options={citiesOption}
          value={city}
          onChange={handleCity}
          className="basic-single"
          classNamePrefix="select"
          isRtl
          placeholder="استان مورد نظر"
          as={Select}
        />

        {errors.citySelect && <p>choose a city</p>}

答案 5 :(得分:0)

React-Select

Bootstrap 5 validation 样式

class CustomSelect extends React.Component {
  render() {
    const { valid, invalid } = this.props;

    let borderColor = '#ced4da';
    let focusBorderColor = '#66afe9';
    let focusBoxShadow = '0 0 0 .2rem rgba(0, 123, 255, 0.25)';
    if (valid) {
      borderColor = '#198754';
      focusBorderColor = '#198754';
      focusBoxShadow = '0 0 0 .2rem rgba(25, 135, 84, .25)';
    } else if (invalid) {
      borderColor = '#dc3545';
      focusBorderColor = '#dc3545';
      focusBoxShadow = '0 0 0 .2rem rgba(220, 53, 69, .25)';
    }
    
    const style = {
      valueContainer: (provided: any, state: any) => ({
        ...provided,
        borderColor: state.selectProps.menuIsOpen ? focusBorderColor : borderColor,
        boxShadow: state.selectProps.menuIsOpen ? focusBoxShadow : 'none',
      }),
    };

    return (
      <Select styles={customStyles} {...this.props} />
    );
  }
}