Closed cnamazone closed 3 years ago
Required in prop types of your component form ?
@cnamazone I guess you can import Select from react-select inside your form container component then pass Select as props.
Then, check the prop type.
But why can't you directly import Select in your form ?
i have the same issue, i need to make my react-select to be required, ex: birth date with year, month ,day dropdown
This might be a dupe of https://github.com/JedWatson/react-select/issues/1453
for security reasons if you cannot validate data then you risk your applications being compromised.
This is on the roadmap for our team in the upcoming set of releases. It's a non-trivial body of work, so we're taking our time to make sure we get it right. Thanks for your patience and understanding everyone. ๐
Any update here?
+1
Any updates?
Is this repo still getting maintained ? Just curious, should I make PR ?
@Rutulpatel7077 @gwyneplaine Managed to do this with custom input component and just passed a flag into props, then got it from props.selectProps.selectProps. It does not seem to support this but it's flexible enough to do kinda everything you want. My app is in clojurescript (bit of interop with js) don't know how helpful a code example would be.
I think the simplest solution is to add another hidden input now. I have added simple input under react-select field.
<Fragment>
<Select {...rest} options={options} filterOptions={filterOptions} />
{!props.disabled && (
<input
tabIndex={-1}
autoComplete="off"
style={{ opacity: 0, height: 0 }}
value={value}
required={required}
/>
)}
</Fragment>
https://codesandbox.io/s/react-select-v2-required-input-3xvvb?fontsize=14
In some cases you do need position absolute
in style
Hey, so I got this asterisk to appear as desired, looks exactly like the built in one. This is for fully managed fields, so there's no form tag, I disable the form myself with JS. This is the big problem I had, and searching led me here.
I make a wrapper component and give the Select a className like "my-className" in the props, and I append " required"
to the className based on a required prop. That's not classNamePrefix
Then apply this css
.my-className.required::after {
content: "*";
color: rgb(255, 95, 95);
position: absolute;
top: -5px;
right: -10px;
}
Like this:
Any update on this?
Any ETA on this?
Hi, i used ref to make the input field required on componentDidMount, you can try the same.
On Wed, 29 Jul 2020, 20:25 Giancarlo Brusca, notifications@github.com wrote:
Any ETA on this?
โ You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/JedWatson/react-select/issues/3140#issuecomment-665713970, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFKDT4CTDO3FNHEN2KACILDR6AZ6VANCNFSM4F647WEA .
Hi, i used ref to make the input field required on componentDidMount, you can try the same. โฆ On Wed, 29 Jul 2020, 20:25 Giancarlo Brusca, @.***> wrote: Any ETA on this? โ You are receiving this because you commented. Reply to this email directly, view it on GitHub <#3140 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFKDT4CTDO3FNHEN2KACILDR6AZ6VANCNFSM4F647WEA .
this.topicRef.current.select.inputRef.required = true;
I'm using the version 3.1.0. I couldn't access to the input ref. I created a simple Select wrapper.
import React from 'react'
import Select from 'react-select';
const SelectWrap = props => {
const { value, required, disabled, className } = props;
let pardeValue = value;
if(Array.isArray(value) || typeof value === 'object')
pardeValue = Object.keys(value).length > 0 ? value : "";
return (
<div className="select-wrapper-container">
<Select {...props} className={`${className} select-wrapper`}/>
<input
className="input-required"
type="text"
value={pardeValue && JSON.stringify(pardeValue)}
tabIndex={-1}
autoComplete="off"
required={required}
disabled={disabled}
/>
</div>
)
}
export default SelectWrap
The style can be more simple, but I want to make my hidden input the same size of the select.
.select-wrapper-container{
position: relative;
.select-wrapper{
position: relative;
z-index: 1;
}
.input-required{
position: absolute;
border: 0;
color: transparent;
background-color: transparent;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
}
}
The best way I found is to create a transparent input field that will be queried via javascript standard checkValidity. This should have absolute positioning and 100% width & height. You can then bind a listener to the input field for the invalid event created by checkValidity
Here is the code I use. There are alterations for use of value field as well as some styling (for MDB inputs) , but you can just change the classes of input to match your own styles libraries. In this manner your validation styling will be the same as your existing form inputs.
Hopes this helps someone.
/**************************************************************************************
*** 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>
)
}
serously, this has been open for 2 years? ๐ฎ
I worked a solution for this - if I remember on Tuesday I'll post it
Mike Thomson Intelliflex Software ๐ 0431817772
From: Gabor Orszaczky notifications@github.com Sent: Friday, October 2, 2020 3:39:44 PM To: JedWatson/react-select react-select@noreply.github.com Cc: Mike Thomson mike.intelliflex@outlook.com; Comment comment@noreply.github.com Subject: Re: [JedWatson/react-select] How to make react-select required in a form? (#3140)
serously, this has been open for 2 years? ๐ฎ
โ You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/JedWatson/react-select/issues/3140#issuecomment-702535650, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AL6F6V3DYB7TTHQZDUOMW63SIVRSBANCNFSM4F647WEA.
Ok I went to post my solution and realised I had already done this in part. I also see people giving me a thumbs down for my attempt to help. You are using a free product that someone has taken the time to share and then want to be critical when others contribute to peoples problems. Go pay for a commercial licence and their support and perhaps you can feel justified. I'll be buggered if I want to help you.
any update on isRequired option in props
I've started a fork of react-select. Feel free to resubmit this issue on the fork and/or submit a PR to resolve this issue on the fork and we can get it merged and released.
EDIT: :tada: I've archived the fork now that we've got some momentum in this repo and Jed is involved again. Sorry for the disturbance!
this would be cool
I would say at this point, this feature is blocked by onBlurClearInput
as this will cause the default behavior of the Select to always fail the required validation. If we add this feature first, then validation could be opt-in in correlation with this prop.
The best solution I can think of is making this be a controlled input: 1) onInputChange, if action is 'focus-blur' and it is a valid option, then setInputValue back to the inputValue
2) const Input = props => <components.Input {...props} required={props.selectProps.required} />
However, this will not work for isSearchable = false
though.
I am also still trying to wrap my mind around the issue of mobile causing the keyboard to popup even if it's not searchable because the select is still focusing on an input. I think isSearchable perhaps should receive a controlled dummySelect so that the validation rules better reflect the use case though Im not certain if that solves mobile usability.
@Intelliflex
Ok I went to post my solution and realised I had already done this in part. I also see people giving me a thumbs down for my attempt to help. You are using a free product that someone has taken the time to share and then want to be critical when others contribute to peoples problems. Go pay for a commercial licence and their support and perhaps you can feel justified. I'll be buggered if I want to help you.
Sorry and I do not understand why so many people in the community gave you a thumbs down. It's frustrating to spend so much time helping people solve their problems without appreciation because the silver platter wasn't shiny enough. I personally have been making a solid effort to close out issues with examples and I understand in some cases it might not even be looked at. In the end though, there's always the developer with years less experience trying to get started and if I can fill that one knowledge gap, cool.
All that to say, whether you decide to share or not, I don't blame you either way. I simply appreciate you being a part of the community. We can always use more builders than critics. ๐ป
I have created a comprehensive ticket to capture the remaining open issues requesting validation and isRequired. https://github.com/JedWatson/react-select/issues/4327
If you want to be a part of shaping the way forward with this feature or are curious about the complexities holding up this feature, please hop in and contribute to the conversation.
That said, I will be closing this ticket to focus our collective efforts related to this feature in #4327
Somebody on the holy internet has solved this, until we have isRequired prop. https://codesandbox.io/s/react-select-v2-required-input-3xvvb
Yes itโs solved, i have a new library coming soon called bootflex. This is a bootstrap themed layout, form and context library, that will handle validation of inputs bootstrap style but with schema support (so input is as simple as with all the usual properties. It should be up on npm by start of Jan. It includes full editor features that incorporate react-hook-form.
Cheers Mike Intelliflex
Mike Thomson Intelliflex Software
From: Jawwad Zafar notifications@github.com Sent: Friday, December 18, 2020 7:26:10 PM To: JedWatson/react-select react-select@noreply.github.com Cc: Mike Thomson mike.intelliflex@outlook.com; Mention mention@noreply.github.com Subject: Re: [JedWatson/react-select] How to make react-select required in a form? (#3140)
Somebody on the holy internet has solved this, until we have isRequired prop. https://codesandbox.io/s/react-select-v2-required-input-3xvvb
โ You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/JedWatson/react-select/issues/3140#issuecomment-747969143, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AL6F6V5SDD7V2AFH3CLFEDLSVMN3FANCNFSM4F647WEA.
Somebody on the holy internet has solved this, until we have isRequired prop. https://codesandbox.io/s/react-select-v2-required-input-3xvvb
Bless his GitHub account!!!!
๐ข Sorry for you if you want isMulti
as it wont work
Bless his GitHub account!!!! ๐ข Sorry for you if you want
isMulti
as it wont work
Don't worry. I'm sure any of the 27-57 people who downvoted Intelliflex will post a solution for the community any day now... ๐
Sarcasm aside, I know at least one other collaborator had began some work on this and I started a WIP to see how this could be resolved as well.
I would suspect this would be able to be done for isMulti
if a visually hidden input was added to the ValueContainer which changed its value as the onChange
was fired. I would like to get to this at some point, but likely a majority of the focus will be on closing out a11y issues, resolving issues related to menu behavior, and working on an unstyled version of react-select.
Form managers such as react-hook-form and formik handle this programmatically with much better logic separation for validation, but for simple cases, I agree that it would be nice to have this "out-of-the-box".
Somebody on the holy internet has solved this, until we have isRequired prop. https://codesandbox.io/s/react-select-v2-required-input-3xvvb
Give this man a cookie!
Thank You @Rutulpatel7077 Your solution solve my issue
Still no updates...noice!
such a fix should be included in an official release
With react-hook-form, the following is working for me.
<Controller
control={control} // from useForm()
name="countryCode"
rules={{ required: true }} // ๐ This bit!
render={({ field }) => (
<Select
options={countryCodes}
onChange={(val: any) => field.onChange(val.value)}
/>
)}
/>
The required
attribute is used (among other things) to communicate to screen readers that the field must be filled in.
Therefore using react-hook-form
's validation to require the value at validation time is not the same as adding the required
attribute, unfortunately. Validation can only do this after submit/change, which is not great in terms of usability. It is better if this is communicated in advance, when first encountering the field.
Similarly, hidden inputs are not a solution, since the input a user will interact with will not be announced as required.
I understand that perhaps the native required
attribute will cause issues with form validation if you're clearing inputs. I would therefore suggest mapping a required
prop to aria-required="true"
attribute on the input. This will fix the accessibility issue whilst also avoiding triggering native form validation.
This is a critical accessibility issue, and it is sad that it has not been fixed in 4 years
I've used the solution of the codesandbox link a few replies above But in my case I'm using the chakra react select wrapper from csandman (and functional components) I wanted not only to have the focus but also the "invalid" red border, not the focus border It's ugly and maybe there something easier but I'll put some stuff below that might be useful for others
First to make it work for functional component, I have :
Then for the red border, I want to use the isInvalid prop from chakra react select
So I added a new state/bool + the isInvalid prop on the select
And now when the input's onFocus is called, I set the isInvalid (also reset it back onChange)
Finally I have to blur to exit focus and have the red border shown (I needed to still call focus to auto scroll to field)
I wrote this fast but basically my input onFocus contains this ugly baby
selectRef.current.focus();
setIsInvalid(true);
selectRef.current.blur();
Using v5 of react-select, I am able to pass the required attribute to the input by creating a custom component for the Input.
export const Input = <
Option extends OptionType,
IsMulti extends boolean,
>(props: InputProps<Option, IsMulti>): ReactElement => (
<selectComponents.Input required={props.selectProps.isRequired} {...props}>
{props.children}
</selectComponents.Input>
);
<ReactSelect
components={{Input}}
isRequired={isRequired}
...
/>
isRequired
needed to be added to a declaration file then passed to ReactSelect.
EDIT: use v5.6 ๐ https://github.com/JedWatson/react-select/issues/3140#issuecomment-1387215825
Using v5 of react-select, I am able to pass the required attribute to the input by creating a custom component for the Input.
export const Input = < Option extends OptionType, IsMulti extends boolean, >(props: InputProps<Option, IsMulti>): ReactElement => ( <selectComponents.Input required={props.selectProps.isRequired} {...props}> {props.children} </selectComponents.Input> );
<ReactSelect components={{Input}} isRequired={isRequired} ... />
isRequired
needed to be added to a declaration file then passed to ReactSelect.
I believe selectComponents
refers to components
in react-select
exports.
Following @michaelmccomiskey 's approach of customizing component, required
prop did pass down to input
. Since i'm lazy, i didnt add extra prop but reuse the required
prop in Select props. But then, i encountered input
always triggered the "Please fill out this field" when submit even if selected sth (regardless of isMulti
). That's because the selected value was put as div
and not set in input
. I expect that if value is set in Select
, the required
check in input
should pass. Therefore, i change a bit on the required
condition:
import Select, {components, InputProps} from 'react-select';
const Input = <Option, IsMulti extends boolean>(props: InputProps<Option, IsMulti>) => {
return <components.Input {...props} required={ props.selectProps.required && !props.hasValue }>
{props.children}
</components.Input>
};
...
export default () => {
return (
...
<Select
components={{Input}}
required={true}
/>
...
)
}
Somebody on the holy internet has solved this, until we have isRequired prop. https://codesandbox.io/s/react-select-v2-required-input-3xvvb
but you cannot use this in same page with diffrent option type.. Do you have solution for it..?
With version 5.6
came required validation in form of the required
prop.
It currently requires the name
prop to work, but #5536 will make the name
prop optional (synonymous to default HTML form elements).
For older versions I recommend following approach:
declare module 'react-select/dist/declarations/src/Select' {
export interface Props<
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>
> {
required?: boolean;
}
}
...
const RequiredInput = ({ onFocus }: { onFocus: FocusEventHandler<HTMLInputElement> }) => (<input
type="text"
required
aria-hidden="true"
tabIndex={-1}
style={{
opacity: 0,
pointerEvents: 'none',
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
width: '100%'
}}
onFocus={onFocus}
/>);
const RequiredControl = <Option, isMulti extends boolean>(props: ControlProps<Option, isMulti>) => {
const { selectProps, hasValue } = props;
return (<React.Fragment>
<components.Control {...props} />
{(selectProps.required && !selectProps.isDisabled && !hasValue) && <RequiredInput onFocus={(e) => {
e.preventDefault();
e.stopPropagation();
document.querySelector<HTMLInputElement>(`#${selectProps.inputId}`)?.focus();
}} />}
</React.Fragment>);
};
<Select
components={{
Control: RequiredControl
}}
inputId="test"
required
/>
So long story short, from 5.6
on, if you want to use required
, combine it with a name
attribute in the Select. For example: <Select name="foo" required ... />
As seen in this example.
As you run, notice that clearing the Select sets its value
attribute to null
. However, at the same time, it displays the "Please fill out this field", which may be undesirable.
So long story short, from
5.6
on, if you want to userequired
, add aname
field in the select. Example:<Select name="foo" required ... />
This is actually working! thank you so much!
So long story short, from 5.6 on, if you want to use required, add a name field in the select. Example: <Select name="foo" required ... />
This does not seem to work with CreatableSelect
. Any ideas?
I solved similar problem with:
In my return where I have some form with Multi Select input:
.....
.....
<Select
isMulti
closeMenuOnSelect={false}
className={error ? 'has-error' : ''}
options={options}
value={selectedOptions}
onChange={setSelectedOptions}
/>
{error && <p className="error-message" style={{color:'red'}}>{error}</p>}
.....
.....
On some handle function before Send form:
if (selectedOptions.length === 0) {
setError('You must choose at least one option!');
return;
}
// Reset error
setError(null);
And of course at the top you need to define State for storing:
const [error, setError] = useState(null);
I hope this helps someone with similar problems
Anyone has found a good way to do this with CreatableSelect
?
I need to make react-select required in a form,