How to disable <react-date-picker> component on a button click - reactjs

I have used a date picker component from react-date-picker. I need to disable the entire date control and the button itself on a single button click. The button does get disabled but the DatePicker component doesn't. I have tried the following but didn't work. Is there a correct way to do it?
import DatePicker from 'react-date-picker';
...
...
this.state = {
disabledDate: false
}
...
...
...
noDateRememberButtonClick() {
this.setState({
disabledDate: true
});
}
render() {
return(
<div className="wrapper">
<div className="date-picker">
<DatePicker
onChange={this.dateOnChange}
value={this.state.boughtDate}
disabled={this.state.disabledDate} />
</div>
<button className="btn" onClick={this.noDateRememberButtonClick} disabled={this.state.disabledDate} type="button"> {BUTTON_LABEL}</button>
</div>
)}

<DatePicker
ref={endCalendarRef}
readOnly={true}
.....
/>

react-date-picker doesn't support the disabled prop. See https://github.com/wojtekmaj/react-date-picker
Per shaz's recommendation, react-datepicker (https://github.com/Hacker0x01/react-datepicker/blob/master/docs/datepicker.md) does, if you would like to use that component instead

Try this. works for me
const CustomInput = (props) => {
return (
<input
className={[classes.TransparentInput, "uk-input"].join(" ")}
onClick={props.onClick}
value={props.value}
type="text"
readOnly={true}
/>
)
}
<DatePicker
customInput={<CustomInput />}
name={'from'}
value={values['from']}
onChange={e => setFieldValue('from', moment(e).format('L'))}
/>
The setFieldValue is from formik. You can choose not to use formik. your choice.

As a hacky workaround (don't feel like taking another library), this worked for me:
Add a disabled class on a container, that wraps the DatePicker
.disabled {
pointer-events: none;
input {
background: transparent;
box-shadow: none;
border: none;
}
}
EDIT: The input styling is only needed, if you wanna make the field look like plain text only.

Related

How to change style of input tag based on checkbox?

I have input form and input tag as a button.
Before I was able to make a button which changed styling according to clicking on it but now i try to make this input gray until user check the checkbox. I tried to use <Show> and when property but i cant use when on <Show> tag. Then I tried to use onChange property and it seem to not give me any errors. I just don't understand how can I change styling inside class=" and then connect it to checkbox function? My checkbox is made by using createSignal
Any ideas?
<input
onChange={functionForStyling}
name="submit"
type={"submit"}
value={"Sign up"}
class=""
/>
Assigning a class to a checkbox element is not different than assigning it to any html element.
Here is how you can assign a class to an html element conditionally.
import { createSignal, JSX } from 'solid-js';
import { render } from 'solid-js/web';
const App = () => {
const [isChecked, setIsChecked] = createSignal(true);
const toggle = () => setIsChecked(c => !c);
const handleChange: JSX.EventHandler<HTMLInputElement, Event> = (event) => {
setIsChecked(event.currentTarget.checked);
};
return (
<div>
<style>{`
input.checked {
transform: rotate(45deg);
}
input.unchecked {
transform: rotate(45deg);
}
`}</style>
<input
type='checkbox'
class={isChecked() ? 'checked' : 'unchecked'}
checked={isChecked()}
onChange={handleChange}
/>
{` `}
<button onclick={toggle}>Toggle</button>
</div>
);
};
render(() => <App />, document.body);
https://playground.solidjs.com/anonymous/163ffec6-1293-4702-9ef6-0425461328c3
Please keep in mind that styling a checkbox is not that straightforward. You need to use pseudo selectors etc.

Reset cursor to the start on <textarea> React

i have a textarea in react that i want to create and i want the cursor the start at the beginning when it loses focus. How do i solve this issue?
codesandbox: https://codesandbox.io/s/affectionate-tu-2cd6j6?file=/src/App.js
``
export default function App() {
const textareaRef = useRef();
return (
<div>
<textarea
ref={textareaRef}
id="my-text-area"
defaultValue={"Hello World!"}
rows="2"
tabIndex="-1"
style={{ resize: "none", overflow: "hidden" }}
onBlur={() => textareaRef.current.setSelectionRange(0, 0)}
></textarea>
</div>
);
}
tried using onblur function with setSelectionRange but its not working for some reason.
Played a bit with your code, seems like you are missing focus() call after changing the selection range.
onBlur={() => {
textareaRef.current.setSelectionRange(0, 0);
textareaRef.current.focus();
}}
Then, the cursor will appear at the beginning of the textarea content.
https://codesandbox.io/s/suspicious-tdd-r8t77j?file=/src/App.js

Dynamically style components passed as props

The goal is to style a prop inside a function (if the prop exists).
More specifically, I basically pass an icon (from styled-icons) as a prop to it and it is supposed to add styling to that icon.
This works with warnings:
const InputRounded = ({ type, placeholder, icon }) => {
const Icon = styled(icon)`
color: #807da0;
width: 1.75rem;
margin: 0 1.25rem 0 0.75rem;
`
return (
<Container>
<Input type={type} placeholder={placeholder} />
<Icon />
</Container>
)
}
Here is how I call it:
import { LockPassword } from '#styled-icons/remix-line'
<Input type="password" placeholder="Password" icon={LockPassword} />
I am aware that one shouldn't create a component inside a function, but I have tried numerous ways otherwise and haven't reached anywhere. Any help for a better method would be greatly appreciated.
You can, very simply, pass a style prop to icon.
const InputRounded = ({ type, placeholder, icon: Icon }) => {
return (
<Container>
<Input type={type} placeholder={placeholder} />
<Icon style={{ color: '#807da0', ... }} />
</Container>
)
}
You could probably use the cloneElement method in React
https://reactjs.org/docs/react-api.html#cloneelement
return (
<>
{ React.cloneElement( icon, [props] }
</>
)
It is similar to
<element.type {...element.props} {...props}>{children}</element.type>
To override some values you can do inline styling.
or otherwise you could use some css classes to override with selectors as well.
if you are going to use styled-icons
you can just simply provide it the props directly.
Styled Icons accept all the valid props of an <svg /> element
https://github.com/styled-icons/styled-icons#props

React material-table: How can I override the style of title in material-table?

I am using material-table "https://material-table.com/"
This is my component that renders a table of data. Here, I am using a custom button inside title for adding new data. It is inside title so that the button goes on the top-left side. I am not using the default add option given by material-table because I want to display a separate form page for adding data instead of inline-adding given by material-table. It works perfectly.
The problem is that the default styling of title has overflow:hidden which can be seen by inspecting it.
<div class='MTableToolbar-title-35'> .... </div>
I want this overflow:hidden to be overflow:auto. How can I override the styling of this title?
export const EmployeeView = ({columns,data}) => {
return (
<div>
<MaterialTable
columns={columns}
data={data}
title={
<div>
<IconButton size='small' color='primary' onClick={() => console.log("Add employee")}>
<AddCircleIcon />
</IconButton>
</div>
}
onRowClick={(event,rowData) => console.log(rowData)}
/>
</div>
)
}
Please use this in the css file
.MuiTypography-h6{
font-size: 1rem;
color: red;
overflow:auto
}
I mentioned the color and font size for testing.

React DatePicker how to open datepicker on click of icon

Trying to open datepicker on click of icon of react-datepicker component, I have gone through their docs and issues links but found that its not much useful.
<DatePicker
{...startDateOpts}
id='abc'
maxDate={moment()}
onChange={this.handleStartChange}
placeholderText='Start Date'
popoverAttachment={smallScreen ? 'bottom center' : undefined}
popoverTargetAttachment={smallScreen ? 'top center' : undefined}
popoverTargetOffset={smallScreen ? '0px 0px' : undefined}
/>
I tried from React-datepicker docs link but no luck.
Just wrap DatePicker with label. All click inside label call focus on input, that open calendar.
<label>
<DatePicker/>
</label>
If you want to programmatically open the datepicker or if you just don't want to use a <label> wrapper you can set a ref to the datepicker component and use setOpen(bool) to open it. Notice that since we're using refs, the component should be stateful.
Example:
openDatepicker = () => this._calendar.setOpen(true);
render() {
<Datepicker
{...datepickerProps}
ref={(c) => this._calendar = c} />
<img src={iconImg} onClick={this.openDatepicker} />
}
There is currently an open issue on the datepicker's Github stating that this is missing from the docs.
I have just finished that by that way,
svg icon has been imported by webpack
import IconCalendar from 'IconCalendar';
the render function in main component
render() {
const {reportSettings: {
dateTo
}} = this.props;
return (
<div id="date-picker">
<Label for="date-picker-1">Select Results date</Label>
<DatePicker todayButton={"Today"} dateFormat={Constants.DATE_FORMAT} customInput={(<ExampleCustomInput/>)} selected={dateTo} onChange={this.handleChange}/>
</div>
);
}
Secondary component that renders input field and icon
class ExampleCustomInput extends Component {
static propTypes = {
onClick: PropTypes.func,
value: PropTypes.string
}
render() {
const {value, onClick} = this.props;
return (
<div className="form-group">
<input type="text" className="form-control" value={value} onClick={onClick}/>
<IconCalendar className="date-picker-icon" onClick={onClick}></IconCalendar>
</div>
);
}
}
finally css helped me to display icon on input field
.date-picker-icon {
float: right;
margin-right: 6px;
margin-top: -30px;
position: relative;
z-index: 2;
}
After adding newer version of react-datepicker i.e. 0.30.0 i got props autofocus but, again I got problem that only worked for first time then i tried using ref like below
refs='startDate'
in datepicker then in this object i got
this.refs.startDate.deferFocusInput();
So i called it and I got date-picker open on click of icon
This can be achieved using ref as below:
const datepickerRef = useRef(null); // OR React.createRef(); if you are not using hooks
// OPENS UP THE DATEPICKER WHEN THE CALENDAR ICON IS CLICKED FOR THE INPUT FIELD
function handleClickDatepickerIcon() {
const datepickerElement = datepickerRef.current;
// console.log("datepickerElement = ", datepickerElement);
datepickerElement.setFocus(true);
}
<DatePicker
{...startDateOpts}
id="abc"
maxDate={moment()}
onChange={this.handleStartChange}
placeholderText="Start Date"
popoverAttachment={smallScreen ? "bottom center" : undefined}
popoverTargetAttachment={smallScreen ? "top center" : undefined}
popoverTargetOffset={smallScreen ? "0px 0px" : undefined}
ref={datepickerRef} // attach the ref
/>;
{/* CALENDAR ICON */}
<span className="calender-placment" onClick={() => handleClickDatepickerIcon()}>
<i className="fal fa-calendar-alt" />
</span>
Added in version 0.30.0, I think the customInput prop would allow you to do this. That way you could create your own input component and attach the onClick handler to the icon inside it.
#Jayant Patil I have achieved the functionality of opening react-datepicker on click of an icon.
This is how I did it.
I have created a wrapper component around the date picker and passed an id as props to it.
class DateRangePicker extends React.Component {
constructor(props, context) {
super(props, context);
// DatePicker is a controlled component.
// This means that you need to provide an input value
// and an onChange handler that updates this value.
}
render() {
return <DatePicker
id={this.props.id}
selected={this.props.selected}
onChange={this.props.onChange}
onChangeRaw={this.props.onChangeRaw}
onBlur={this.props.onBlur}
peekNextMonth={true}
showMonthDropdown={true}
showYearDropdown={true}
dropdownMode="select"
placeholderText="MM/DD/YYYY"
dateFormat="MM/DD/YYYY"
shouldCloseOnSelect={true}
defaultValue={null}
/>
}
}
export default DateRangePicker;
Then enclose your icon using a label and then pass the id.
<DateRangePicker
ref={'calendar1'}
id={'fromdate'}
dateFormat={gridAttributes.DEFAULT_DATE_FORMAT}
selected={this.state.fromDate}
onChange={this.handleDateChange.bind(this, 'fromDate')}
onChangeRaw={(e) => this.handleRawFromDateChange(e)}
onBlur={this.handleFromBlur.bind(this)}
peekNextMonth={true}
placeholderText={gridAttributes.DEFAULT_DATE_FORMAT}
showMonthDropdown={true}
showYearDropdown={true}
defaultValue={null}
className="calendar1"
/>
<label className="icon iconCalendar calendar" style={{ fontSize: '20px' }} htmlFor='fromdate' />
This works without affecting any functionality unlike when only enclosing the icon with label as said by #tre
<label>
<DatePicker/> </label>
causes the calendar to be in open and can be closed only when we click outside the calendar.
I don't know but none of these solutions worked for me. So made the following one:
openDatepicker = (e) => {
// find date picker input element
const inputElement = e.target.closest('.my-wrapper-class')?.querySelector('input')
return inputElement?.click();
}
The accepted answer is having some issues in that, like ->
When user select the date, the calender is not closing on date select, as the <label> trying to setOpen = true again so even after selecting the date, the claendar still open.
How to overcome this issue? see below the simple answer ->
this.state = {
openCalendar : false,
date : new Date()
}
handleChange = date => this.setState({ setDate : date });
render(){
return(
<label>
<DatePicker
selected={this.state.date}
onFocus={() => this.setState({ openCalendar: true })}
onChange={this.handleDateChange}
open={this.state.openCalendar}
/>
//you can add any icon here and on click that, the date will work as expected.
<svg/> //add any icon you want
</label>
)
}

Resources