React-select: Add validation support

Created on 28 Dec 2016  路  58Comments  路  Source: JedWatson/react-select

Hi,

Please add validation support as it is a very important part.

issuenhancement issureviewed

Most helpful comment

Any updates here? I would also love to see this.

All 58 comments

workaround:

export const renderField = ({ input, placeholder, simpleValue, meta: { touched, error }, ...field }) => (
  <div>
    <Select 
      simpleValue={simpleValue}
      errorText={touched && error}
      value={input.value}
      className="defautSelectParent"
      placeholder={placeholder}
      options={field.loadOptions}
      onBlur={() => input.onBlur(input.value)}
      onChange={(value) => { input.onChange(value)} }
      {...field} />
    <div>{(touched && error) && 
      <div style={{'fontSize':'12px','color':'rgb(244, 67, 54)'}}>Required</div>}</div>
  </div>
);

Basically you are adding a label right? But what about coloring the border in red?
Any news on this feature? Can't see it in the demos, neither in docs.

I made in one text input component custom validation with these codes in it

onChange = (e) => {
    if (this.props.validate) {
      e.target.setCustomValidity(this.props.validate(value));
    }
}

Can you add these lines then We can set some string message to validate property and it will show similar like basic required message.

I check and the correct place is here. https://github.com/JedWatson/react-select/blob/master/src/Select.js#L347
So all is done can you make it?

Other option is this:

addValidationMessage(message) {
    this.input.setCustomValidity(message);
  }

+1, also need this here.

Using jquery-validation for form validation.

I'm not sure if this is really the place to put this, but maybe it'll help someone else!

I'm using Bootstrap 4, and I wanted the styling of react-select to be passably similar with regards to focus, and validation colours.

The following isn't perfect, but it was passable for what I needed.
(Which is just single selection, no tags, pretty much just the "basic" single select.)

First I added a couple of classes to the Select control which indicate validation status.

if (isValid) {
    combinedClassName += " reactselect-valid";
} else if (isInvalid) {
    combinedClassName += " reactselect-invalid";
}

Then I modified the styles to work with these classes.


Expand to see SASS

@import "~bootstrap/scss/_variables.scss";
@import "~react-select/scss/select.scss";

.Select {
    &.is-open > .Select-control {
        border-color: $component-active-bg;
    }

    &.is-focused > .Select-control {
        border-color: $component-active-bg;
        box-shadow: 0 0 0 $input-focus-width rgba($component-active-bg, .25);
    }

    &.is-focused:not(.is-open) > .Select-control {
        border-color: $component-active-bg;
        box-shadow: 0 0 0 $input-focus-width rgba($component-active-bg, .25);
    }

    &.is-open > .Select-menu-outer {
        border-color: $component-active-bg;
    }

    &.reactselect-valid {
        .Select-control {
            border-color: $form-feedback-valid-color;
        }

        &.is-open > .Select-control {
            border-color: $form-feedback-valid-color;
        }

        &.is-focused > .Select-control {
            border-color: $form-feedback-valid-color;
            box-shadow: 0 0 0 $input-focus-width rgba($form-feedback-valid-color, .25);
        }

        &.is-focused:not(.is-open) > .Select-control {
            border-color: $form-feedback-valid-color;
            box-shadow: 0 0 0 $input-focus-width rgba($form-feedback-valid-color, .25);
        }

        &.is-open > .Select-menu-outer {
            border-color: $form-feedback-valid-color;
        }
    }

    &.reactselect-invalid {
        .Select-control {
            border-color: $form-feedback-invalid-color;
        }

        &.is-open > .Select-control {
            border-color: $form-feedback-invalid-color;
        }

        &.is-focused > .Select-control {
            border-color: $form-feedback-invalid-color;
            box-shadow: 0 0 0 $input-focus-width rgba($form-feedback-invalid-color, .25);
        }

        &.is-focused:not(.is-open) > .Select-control {
            border-color: $form-feedback-invalid-color;
            box-shadow: 0 0 0 $input-focus-width rgba($form-feedback-invalid-color, .25);
        }

        &.is-open > .Select-menu-outer {
            border-color: $form-feedback-invalid-color;
        }
    }
}

I found a work around

Setp -1 : Add a variable in the Component Class
hiddenInput = null;

Step-2 Add a method

HighlightIfInError = () => {
if (this.hiddenInput != undefined) {
let el = this.hiddenInput;
while ((el = el.parentElement) && !el.classList.contains("Select-control"));
if (this.hiddenInput.hasAttribute("required")) {
el.style.border = "1px solid red";
} else {
el.style.border = "";
}
}
};

This method will be called from the component where validation is happening
this.ComponentRefToComponentHavingReactSelet.current.HighlightIfInError();

Step -3 : Change the componentDidUpdate method

**componentDidUpdate = () => {
    this.hiddenInput = document.getElementById(`chaperone-search-${this.props.row_key}`);
};**

Step 4 : Update the Select component that is a child component

...
required={true}
**inputProps={{
id: chaperone-search-${this.props.row_key},
name: chaperone_search_${this.props.row_key}
}}**
/>

Note : this.props.row_key should be a unique value

Let me know if it helped. For me it worked

Here's a simple workaround that works well with React Bootstrap plugin

<Select style={{ borderColor: this.state.someValidationError ? "#b94a48" : "#aaa"}} .../>

Any news on this?

I needed to mark required fields as such so I ended up passing a custom placeholder when I need to show "Required" validation labels:

placeholder={isValid ? "Normal text placeholder" : <span className="text-danger">Required</span>}

Yeah.. big one for me. If the user can input invalid data they can break the data model.

Is anything planned about this ? I need it too !

That's a pretty important feature... not everybody wants a controlled component and will just use standard HTML validation for forms.
And even if you are fine with a controlled components, it's some validation you don't have to do when the form is submitted.
It's a very basic feature to have: required, pattern, ...
I'm fine trying to make a PR for it if it'll get accepted and merged

@dcousens @JedWatson

@fbarbare I'm not a maintainer for this project actually! Sorry, can't help on this one :+1:

@JedWatson is on holiday.

Any updates here? I would also love to see this.

Looking forward for this feature!

bump!! looking forward too

Any updates? Looking forward to this feature.

Has anyone tried making a PR to add it? It doesn't seem like it would be too hard. I suggest doing that instead of asking other people to do it.

Same for me, would be great to have invalid prop to make the border red.

Any news? :)

required and pattern and other form validation attributes only work on form elements (select, input). The only element that could be used for such validation is the input element that is assigned the value of the current selection. Unfortunately this element is of type hidden and according to the spec has no constraint validation.

Constraint validation: If an input element鈥檚 type attribute is in the Hidden state, it is barred from constraint validation.

-- Hidden STATE Spec

If you want requirement and validation you can do that inside a submit event handler for a form element. To access the value for validation you can either keep your component controlled and save it in state, use a ref, or just use the event data.

handleSubmit(event) {
    const { state, selectRef } = this;

    // Controlled component. Value is in state.
    if (!state.color.value) { /* No value */ }

    // `ref` with React.createRef()
    if (!selectRef.current.state.value) { /* No value */ }

    // Using the event data to target the hidden `input` element
    if (event.target.color.value) { /* No value */ }
}

<form onSubmit={this.handleSubmit.bind(this)}>
    <Select { ... }
        ref={this.selectRef} // Using ref
        value={this.state.color} onChange={(value, action) => this.setState({ [action.name]: value })} // Controlled component
        name="color" // Event data or controlled component
    />
</form>

If you want to style the select for errors, you can use the styling framework to e.g. show a red border if it is required.

state = { color: null, colorError: false }

handleSubmit (e) {
    const { color } = this.state;


    if (!color) {
        this.setState({ colorError: true });
        // Do other stuff that should happen if `color` is not set
    };

    /* ... */
}

<form onSubmit={this.handleSubmit.bind(this)}>
    <Select { ... } 
        value={this.state.color}
        styles={{
            control: (provided, state) => (this.state.colorError ? {
                ...provided, borderColor: 'red', 
            } : provided)
        }}
    />
</form>

CodeSandbox

Not quick as I hoped but at least is working, thank you very much 馃嵑

Any news? :)

Hi..
i am trying to implement formik validation for react-select(single select)

initialValues={{
department:"",
}}
onSubmit={this.submitForm}
validationSchema={Yup.object().shape({
department: Yup.object().shape({
label: Yup.string().required(),
value: Yup.string().required(),
}),
})}
>
{props => {
const {
values,
touched,
errors,
isSubmitting,
handleChange,
handleBlur,
handleSubmit,
selectedOption
} = props;
return (

Department

inputId="department"
options={options}
value={values.department}
onChange={this.onChangeOption}
onBlur={handleBlur}
/>
{errors.department && touched.department && (

)}

                    </div>
              </React.Fragment>
            );
          }}
        </Formik>

how to assign object validation for validationSchema in yup concept
Please check the above code....i am getting this error
"Objects are not valid as a React child (found: object with keys {label, value}). If you meant to render a collection of children, use an array instead."

@taruni29 The Formik library has created an example on how to implement react-select (v1 and v2) into its validation schema. Please consult this codesandbox for more details.

I'm unable to set border color to red.

<Select ... style={{ borderColor: '#dc3545' }} />

^Didn't work for me (2.2.0 version).

@alfonmga Please check the documentation for the styling api.

@Rall3n I don't see react-select in the codesandbox you listed.

@pak11273 Seems like they changed the url. Here is the current link to the sandbox.

(Also updated link in my comment above.)

@Rall3n nice. thanks for the update!

@taruni29 The Formik library has created an example on how to implement react-select (v1 and v2) into its validation schema. Please consult this codesandbox for more details.

the example code is for isMulti what about for single entry only, it return a object not an array

@mtowercamp Just change the validationSchema for the select value to just accept an object, and also change the value compilation in line 30 from mapping over an array to just the value.


Further questions regarding implementation into form libraries should go to StackOverflow to keep this issue from cluttering.

workaround:

export const renderField = ({ input, placeholder, simpleValue, meta: { touched, error }, ...field }) => (
  <div>
    <Select 
      simpleValue={simpleValue}
      errorText={touched && error}
      value={input.value}
      className="defautSelectParent"
      placeholder={placeholder}
      options={field.loadOptions}
      onBlur={() => input.onBlur(input.value)}
      onChange={(value) => { input.onChange(value)} }
      {...field} />
    <div>{(touched && error) && 
      <div style={{'fontSize':'12px','color':'rgb(244, 67, 54)'}}>Required</div>}</div>
  </div>
);

Where and how do I validate in above case and set error ?

Please add the "required" validation! I couldn't get the exact MUI styling with all workarounds I've tried.

I just want to say, that this is still needed.

I've returned to this issue over the lifecycle of react-select 2.x and now react-select 3.x

I need easy solution for "required" ! to integrate formik for validation is stupid !

As a 'solution', which is not a solution at all, I just changed library to availity-reactstrap-validation.
I hope it will help at least someone.

is there any update for this issue? it's really important when using select

+1 for really needed

+1 for really really needed

+1 needed

+1 must have, thanks :)

+1 All I want for Christmas is required and validation support on React Select!

I used this workaround for showing border color with bootstrap: https://github.com/JedWatson/react-select/issues/2930#issuecomment-552455924

You can try that:

const customStyles = (hasError) => ({
  control: (styles: any) => ({
    ...styles,
    ...(hasError && { borderColor: 'red' }),
  }),
});

export default ({ fieldHasError, ...props }) => (
  <Select
    styles={customStyles(fieldHasError)}
  />
);

Set the border color when there are errors...

<Select
  ...
  styles={{
    control: styles => ({
      ...styles,
      borderColor: someBooleanForErrors ? 'red' : styles.borderColor
    })
  }} 
/>

Ran across this and came up with what I thought was a decent solution for v3+. Figured I'd share:

We needed to render the border as "red" if there was an error.

P.S. We use "box-shadow" instead of "border" because it transitions more smoothly (but thats a totally different conversation).

// MySelector.js
<Select error={hasError} styles={customStyles} />


// customStyles.js
const colors = {
    divider: '#d8d8d8',
    error: '#d43f21'
};

export const customStyles = {
    control: (base, state) => {
        let statusColor = colors.divider;

        if (state.selectProps.error) { // "state.selectProps" references the component props
            statusColor = colors.error;
        }

        return {
            ...base,
            boxShadow: `0 0 0 2px ${statusColor}`,
            transition: " 0.25s linear",
            transitionProperty: "box-shadow",
        };
    },
};

+1 for really needed

we can simple overwrite theme depend of validation

const error = true;
<Select theme={reactSelectTheme(error)}
const reactSelectTheme = error => theme => {
  const errorStyling = error
  ? {
      primary: 'red',
      neutral10: 'red',
      neutral30: 'red',
      neutral20: 'red',
      neutral60: 'red',
    }
    : {};

  return ({
    ...theme,
    colors: {
      ...theme.colors,
      ...errorStyling,
    },
  });
};

@DragonRaider5 make good point :

Be careful with this as it creates a new object on each and every render of your select.

so it will be better add useMemo

const theme = useMemo(() => reactSelectTheme(error), [error]);

<Select theme={theme}

we can simple overwrite theme depend of validation

const error = true;
<Select theme={reactSelectTheme(error)}
const reactSelectTheme = error => theme => {
  const errorStyling = error
  ? {
      primary: 'red',
      neutral10: 'red',
      neutral30: 'red',
      neutral20: 'red',
      neutral60: 'red',
    }
    : {};

  return ({
    ...theme,
    colors: {
      ...theme.colors,
      ...errorStyling,
    },
  });
};

Be careful with this as it creates a new object on each and every render of your select.

Still no updates? This issue was opened in 2016!
Would passing "required" through to the inner input work? If not how about rendering a hidden select in the same location as the UI one. Keeping values in sync the HTML validation would run on the hidden select and draw focus / report errors. Styling could be achieved via :invalid pseudo-class on the hidden select. Something like: select:not(:valid) + react-select {color:red}

Basically you are adding a label right? But what about coloring the border in red?
Any news on this feature? Can't see it in the demos, neither in docs.

hey, is there any progress for this?

Here is a work-around! Create a hidden select box that stays in sync with the react-select value. When form validation runs it will fail on the hidden select if marked required with no value set. This also allows for custom error styles via native CSS :invalid pseudo class. IMO this should be built into react-select.

JSX

import React, {useRef, useState, useEffect} from "react";
import Select from "react-select";

import "./Dropdown.scss";

export default ({id, disabled, required, options, multiple, value, defaultValue, onChange, ...props}) => {
    //Refs needed for hidden select validity
    const refSelect = useRef();
    const refReactSelect = useRef();

    //State hooks
    const [stateValue, setStateValue] = useState(defaultValue); //Initial value
    const [stateInvalid, setStateInvalid] = useState(false); //Initial value

    //modifyInvalidState because we don't want to set invalid until onChange
    function customValidity(value, modifyInvalidState) {
        modifyInvalidState = modifyInvalidState === true;

        if (!(refSelect && refSelect.current)) {
            return;
        }

        if (required && normalizeValue(value) == "") {
            refSelect.current.setCustomValidity("Please select a value.");
            if (modifyInvalidState && stateInvalid !== true) {
                setStateInvalid(true);
            }
        } else {
            refSelect.current.setCustomValidity(""); //Remove
            if (modifyInvalidState && stateInvalid !== false) {
                setStateInvalid(false);
            }
        }
    }

    //Run customValidity immediately after ref set so if form is submitted and this is invalid it will fail
    useEffect(() => {
        customValidity(stateValue);
    }, [refSelect]);

    return (
        <div className={`dropdown${stateInvalid ? " invalid" : ""}`}>
            {/* Hidden select for "required" */}
            <label htmlFor={id}>Select a value</label>
            <select
                ref={refSelect}
                id={id}
                disabled={disabled}
                required={required}
                multiple={multiple}
                value={normalizeValue(stateValue)}
                onChange={() => null /* NOP */}
                onFocus={() => refReactSelect.current.focus()}
            >
                <option>{/* Empty option to align with react-select default being empty */}</option>
                {options.map(option => (
                    <option key={`${id}_${option.value}`} value={option.value}>
                        {option.label}
                    </option>
                ))}
            </select>

            <Select
                ref={refReactSelect}
                isDisabled={disabled}
                required={required}
                options={options}
                isMulti={multiple}
                classNamePrefix="slt"
                defaultValue={defaultValue}
                onChange={selected => {
                    setStateValue(selected);

                    //Notify parent
                    if (onChange) {
                        onChange.call(this, selected);
                    }

                    //Run HTML5 validation
                    customValidity(selected, true);
                }}
                {...props}
            ></Select>
        </div>
    );
};

//Normalizes react-select value for standard <select>
function normalizeValue(selection) {
    if (Array.isArray(selection)) {
        if (selection.length) {
            return selection.map(keyPair => keyPair.value);
        }
    } else if (selection && typeof selection.value !== typeof undefined) {
        return selection.value;
    }
    return "";
}

SCSS

.dropdown {
    position: relative;

    //Validation
    &.invalid {
        select:invalid + div .slt__control {
            border-bottom: 2px solid red;
        }
    }

    //Hide select used for validation
    select {
        position: absolute;
        bottom: 0;
        left: 0;
        width: 0;
        height: 0;
        opacity: 0;
        font-size: 0;
    }
}

Greetings everyone!

We have identified this as high priority, moderate complexity, and something that has been requested by others. In an attempt to collect and better serve the intention of this issue, I will be closing this and related tickets requesting required/validation to put priority focus and attention on https://github.com/JedWatson/react-select/issues/4327

I hope you all can join the conversation there as there is new momentum behind this project. We are putting together releases for version v3.2 and v4 (more details coming in the next 24 hours) and your input could help determine if this makes it into either of those two or an even later version.

Thank you and appreciate your patience and input.

@koga, I agree with the approach you posted though there is a bit more complexity due to isSearchable = false, and isMulti. Either way, hoping you have some thoughts in the thread I posted to directly above this.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ericj17 picture ericj17  路  3Comments

coder-guy22296 picture coder-guy22296  路  3Comments

pablote picture pablote  路  3Comments

sampatbadhe picture sampatbadhe  路  3Comments

pashap picture pashap  路  3Comments