How to implement validation/restriction in react-datepicker - javascript

I am trying to implement restriction or validation in a react-datepicker component. I am using redux-form for validation and normalization(to implement restriction)
https://redux-form.com/6.0.0-rc.1/examples/normalizing/
Question : I have observed that neither normalizing function nor validation functions of redux-form is called when we try to enter something in the field
although this value is not submitted when we submit the form but i need to show some validation error or restrict user from typing invalid characters.
I made a wrapper for the date picker component and used it in my form through redux field
my date picker component :-
return (
<div className={"render-date-picker "}>
<div className="input-error-wrapper">
{(input.value) ? <label> {placeholder} </label> : ''}
<DatePicker className="input form-flow" {...input}
placeholderText={placeholder}
selected={input.value ? moment(input.value) : null}
maxDate={maxDate || null}
minDate={minDate || null}
dateFormat={isTimePicker ? "LLL" : "DD/MM/YYYY"}
showYearDropdown
showMonthDropdown
disabledKeyboardNavigation
/>
{touched && error && <span className="error-msg">{t(error)}</span>}
<span className="bar" style={{ 'display': this.state.is_focus ? 'block' : 'none' }} ></span>
</div>
</div>
);
redux form field :-
<Field
name="date_of_birth"
type="text"
className="input form-flow extra-padding-datepicker"
component={RenderDatePicker}
maxDate={moment().subtract(18, "years")}
validate={[required, dateOfBirth]}
normalize={isValidDateFormat}
placeholder={t("DOB (DD/MM/YYYY)")}
/>
my normalizing function:-
export const isValidDateFormat = (value, previousValue) => {
if (value == null || !value.isValid()) {
return previousValue;
}
return value;
}

react-datepicker provides onChangeRaw property to get raw (typed) value inside the datePicker. In order to restrict or validate the datepicker input field we need the raw value which is not available on onChange event of the datepicker component.
for instance if we observe the onChange event :-
It returns a moment object.
In order to get raw value we use onChangeRaw
The raw value is obtained simply from e.target.value.
In my case I simply restrict the user from typing anything in the datepicker input field by a simple function:-
handleChangeRaw = (date) => {
let s=document.getElementById(date_picker_id)
s.value =moment(this.props.input.value).format("DD/MM/YYYY");
}
My datepicker component :-
<DatePicker
.....
disabledKeyboardNavigation
onChangeRaw={(e)=>this.handleChangeRaw(e)}
id={date_picker_id}
.....
/>
This solved my problem. Hope it is useful :)

Related

Display React component only when attribute is not null

MyReactComponent returns a hyperlink and a message after looking up an API using the name value. However I would like to render this component (which includes making the API call) only when name is not empty. Would the below solve the purpose or should I approach this differently?
<dt hidden={null == name || '' === name.trim()}>
<MyReactComponent name={name || ' '} />
</dt>
Here is another way you can do this :
{(name && name.trim() !== '') &&
<MyReactComponent name={name} />
}
You can learn more here.
Instead of using hidden attribute, you can render your component with ternary operator:
{name ? <MyReactComponent name={name} /> : null}

Proper way to change Form.Control text with custom onChange

I noticed today that while using a custom onChange in a Form.Control that the text in the field no longer changes when a file is selected. I have looked through the documentation on the Git HERE but it doesnt say how to change the text with a custom event.
my code:
// handles when a file has been selected.
const handleUploadChange = (event) =>
{
setFileToUpload(event.target.files[0]);
setIsFilePicked(true);
}
// Footer containing buttons and file selection
const CardFooter = () =>{
return(
<Card.Footer>
<div style={{width:"80%", display : "flex", flexDirection: "row", justifyContent: "center"}}>
<div style={{marginRight: "40px"}}>
<Form.Group controlId="formFile" className="mb-3">
<Form.Control type="file" custom onChange={handleUploadChange} label={fileToUpload === null ? "No File Selected" : fileToUpload.name}/>
</Form.Group>
</div>
<div className="btn-red" style={{marginRight: "40px"}}>
<Button disabled={fileToUpload === null} onClick={()=>{setFileToUpload(null); setIsFilePicked(false);}}>Clear</Button>
</div>
<div>
<Button disabled={(fileToUpload === null) || (fileToUpload.size >= maxUploadSizeInBytes)} onClick={()=>handleSubmit(fileToUpload)}>Upload</Button>
</div>
</div>
</Card.Footer>
)
}
As you can see here, once a file is selected, my change event happens, but the selection box still reads "No file chosen". I have attempted label, text, displayName , and placeholder like so: label={fileToUpload === null ? "No File Selected" : fileToUpload.name}
Does anyone know the proper prop to use with a custom onChange ?
You can't control input of type "file" in React. When you choose a file, the text/"label" should automatically be updated. You don't have to manage it. Just set the state on select and read the state on submission. To fix your clear button, you could use useRef:
const fileInputRef = useRef(null);
...
<Form.Control ref={fileInputRef} ...>
...
<Button onClick={() => {
setFileToUpload(null);
fileInputRef.current.value = null;
}}>
Clear
</Button
Also consider following:
You don't need your "isFilePicked" state. It can be derived from "fileToUpload" with Boolean(fileToUpload).
There is no Form.Control custom property.
Nore there is a Form.Control label property. If you need a label, add Form.Label to it. You can hide the file input and style your own input solution if you want to.
Codesandbox:
https://codesandbox.io/s/beautiful-vaughan-zn68t
Read more:
how to hold file input value in react
How to reset ReactJS file input

React-Calendar month view change

I am using React-Calendar and I am unable to change the month bu clicking the arrows (back/ forward) in the navigation panel, where the month name is displayed. My code:
...
const onActiveStartDateChangeHandler = ({ activeStartDate, value, view }) => {
console.log("vv:", activeStartDate, value, view);
};
...
return (
<div className="popupFormSelector arrowLft pb-8">
<h2 className="text-center font-bold mt-7 mb-5">Set a deadline</h2>
<Delete classes="right-5 top-5" onClickHandler={toggleCalendar} />
<Calendar
activeStartDate={teamStartDate}
calendarType="US"
defaultView="month"
maxDetail="month"
maxDate={endDate}
minDate={teamStartDate}
next2Label={null}
onActiveStartDateChange={onActiveStartDateChangeHandler}
onChange={onChangeHandler}
prev2Label={null}
selectRange={false}
showDoubleView={false}
showFixedNumberOfWeeks={false}
showNavigation={true}
showNeighboringMonth={true}
tileClassName={tileClasses}
tileDisabled={({ activeStartDate, date, view }) =>
date < teamStartDate || date > endDate
}
value={new Date()}
view={"month"}
/>
From console.log on handler for onActiveStartDateChange, I can see that the date is changed in the log, however, the view stays at the current month. What am I doing wrong?
The month view doesn't change because it is tied to the value you provided here:
activeStartDate={teamStartDate}
As stated in the docs, this initiates a "controlled" behavior:
activeStartDate The beginning of a period that shall be displayed. If you wish to use React-Calendar in an uncontrolled way, use defaultActiveStartDate instead.
So either use defaultActiveStartDate instead of activeStartDate if it matches your use case, or you could simply update the value of teamStartDate in the method, like this:
const onActiveStartDateChange = ({activeStartDate}) => teamStartDate = activeStartDate

Validating a value when button is pressed before passing it

Hi I am new to React and I am a little bit confused on how to validate a value before passing it to the partialRefund function I have.
I am trying to set a simple validation to make sure the value is not empty and numeric before passing it to the partialRefund function.
The first line is the code I currently have. The second line is the code I am trying to write for the validation but it is not working.
Any help would be really appreciated! Thanks!
//Current code
{partialRefundSelected ? <div> <input id={`partial_refund_${order_id}`} type='text'/> <button onClick={() => partialRefund(order_deets_obj,"partialRefund",document.getElementById('partial_refund_'+order_id).value)}> Refund Order </button> </div> : ""}
//Code I am trying to use
{partialRefundSelected ? <div> <input id={`partial_refund_${order_id}`} type='text'/> <button onClick={(validateValue(document.getElementById('partial_refund_'+order_id).value)) => partialRefund(order_deets_obj,"partialRefund",document.getElementById('partial_refund_'+order_id).value)}> Refund Order </button> </div> : ""}
On the second line i am trying to pass a function that will validate the value and the pass it to the partialRefund function. But it doesnt seem to be working :(
Use this:
{
partialRefundSelected ?
<div>
<input id={`partial_refund_${order_id}`} type='text'/>
<button onClick={() => {
const validatedValue=validateValue(document.getElementById('partial_refund_'+order_id).value));
partialRefund(order_deets_obj,"partialRefund",validatedValue);
}}> Refund Order
</button>
</div> :
""}
You can do the validation in the onClick callback if you add curly brackets around the parttialRefund call.
export default function App() {
const partialRefundSelected = true;
const order_id = 1;
const order_deets_obj = { deets: "good deets" };
const partialRefund = (deets, someString, someValue) => {
console.log(deets, someString, someValue);
};
return partialRefundSelected ? (
<div>
<input id={`partial_refund_${order_id}`} type="text" />
<button
onClick={() => {
const value = document.getElementById("partial_refund_" + order_id)
.value;
// Do validation here
if (value === "I LOVE CATS") {
partialRefund(order_deets_obj, "partialRefund", value);
}
}}
>
Refund Order
</button>
</div>
) : (
""
);
}
While this is an option in react, I would suggest making your input a Controlled Component. This would allow you to keep the input's text in state instead of needing to pull the text off of the element after a click. Here is an example.

How do I make it mandatory to select at least two options using the React Multiselect component?

I created one form control using the React Multiselect component. In this control, I want the 'required' to be removed when at least two of the Multiselect fields are selected.Required does not appear when user selects even one. Required appears only when nothing is selected. How can I do that?
React JS
const changeSelected = (selectedList, selectedItem) => {
const values = selectedList.toString();
setInput({...input, value: values})
dispatch(saveAnswer('f3', formKey, values))
}
return (
<>
<p>{comboboxName}</p>
<Multiselect className='btn-group'
style={{background: "red"}}
isObject={false}
closeIcon="close"
options={options} // Options to display in the dropdown
selectedValues={input.value ? input.value.split(',') : []} // Preselected value to persist in dropdown
onSelect={changeSelected} // Function will trigger on select event
onRemove={changeSelected} // Function will trigger on remove event
placeholder=''
/>
<p></p>
<Form.Check>
<Form.Check.Input required
checked={input.value != null && input.value.length > 1}
style={{display:'none' }}
/>
<Form.Control.Feedback type="invalid" >Required</Form.Control.Feedback>
</Form.Check>
</>
)
I guess this would solve your problem:
<Form.Check.Input
required = {input.value.length < 2 ? true : false}
checked={input.value != null && input.value.length > 1}
style={{display:'none' }}
/>

Categories

Resources