When I add onBlur and onFocus with setStates to datePicker in the blitz demo provided for the component I was able to create an infinite loop with this code
https://zvfckz.run.stackblitz.io/
-Steps to reproduce with following code, click outside component of opened one so they are all close
-Click on Format and WeekColumn calendar icon to have it open and then click Default Show(edited) icon and this will create an infinite loop
This create a setState loop but I am curious to why as these component are separate.
5 Answers, 1 is accepted
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DatePicker,DateTimePicker } from '@progress/kendo-react-dateinputs';
import { DropDownList } from '@progress/kendo-react-dropdowns';
import { IntlProvider, load, loadMessages, LocalizationProvider } from '@progress/kendo-react-intl';
import likelySubtags from 'cldr-core/supplemental/likelySubtags.json';
import currencyData from 'cldr-core/supplemental/currencyData.json';
import weekData from 'cldr-core/supplemental/weekData.json';
import numbers from 'cldr-numbers-full/main/es/numbers.json';
import caGregorian from 'cldr-dates-full/main/es/ca-gregorian.json';
import dateFields from 'cldr-dates-full/main/es/dateFields.json';
import timeZoneNames from 'cldr-dates-full/main/es/timeZoneNames.json';
load(
likelySubtags,
currencyData,
weekData, numbers,
caGregorian,
dateFields,
timeZoneNames
);
import esMessages from './es.json';
loadMessages(esMessages, 'es-ES');
class App extends React.Component {
locales = [
{
language: 'en-US',
locale: 'en'
},
{
language: 'es-ES',
locale: 'es'
}
]
state = { selectedLocale: this.locales[0], value: new Date(),showIt:true };
render() {
return (
<LocalizationProvider language={this.state.selectedLocale.language}>
<IntlProvider locale={this.state.selectedLocale.locale}>
<div className="example-wrapper row">
<div className="col-xs-12 col-md-12 example-config">
<h6>Locale: <DropDownList
value={this.state.selectedLocale}
data={this.locales}
textField={'locale'}
onChange={(e) => {
this.setState({ selectedLocale: e.target.value });
}}
/>
</h6>
</div>
<div className="col-xs-12 col-md-6 example-col">
<p>Default Show</p>
<DateTimePicker value={this.state.value} show={this.state.showIt}
onFocus={()=>{this.setState({showIt:true})}}
onBlur={()=>{this.setState({showIt:false})}}
onChange={(e)=>{this.setState({value:e.target.value})}}/>
<p>Format and WeekColumn</p>
<DatePicker defaultValue={new Date()} format="dd/MMM/yyyy" weekNumber={true} />
<p>Disabled</p>
<DatePicker disabled defaultValue={new Date()} format="dd/MMMM/yyyy" />
</div>
</div>
</IntlProvider>
</LocalizationProvider>
);
}
}
ReactDOM.render(
<App />,
document.querySelector('my-app')
);
Hello, Jason,
Thank you for your example.
The issue occurs because when the second DatePicker is opened its Calendar is also focused. This caused the first DatePicker to blur and starts the endless loop.
This could be resolved by using a custom Calendar in the second DatePicker that will not focus automatically
https://stackblitz.com/edit/react-rps4zt-uq9mkx?file=app/main.jsx
In general, we do not recommend using the focus and blur events for opening and closing the DatePicker as they are synchronous events and cause different issues.
Please let me know the main desired result as we may be able to suggest an alternative approach.
Regards,
Stefan
Progress Telerik
Thank you for the quick reply.
The main reason I am passing onBlur and onFocus to the DatePicker is because I have added a clear button that shows up onFocus but hide it onBlur. This fixes the issue of the loop by passing it a Calendar prop but now I am having an issue where the Now, Set and Cancel buttons seem to no longer close the modal. here is a rough skeleton of my component
// I understand that this is still due to onFocus being on the component but could not find a child component for the time picker or confirmation buttons
<DatePicker
//value
//format
onChange={this.setDate} // sets values where needed
Calendar={Calendar} // passed import Calendar -- thanks again
show={this.state.showCalendar}// state of show due so when clicked input box shows calendar pop up
onFocus={() => {
this.openCancel(true); // this method changes the state of this.state.showCalendar and showClearButton state
}}
onBlur={() => {
this.openCancel(false); // reverse of onFocus as i no longer need the clear button or to show the calendar as show is prop based
}}
/>
// this.state.showCancel ? // show clearButton which clears values onMouseDown as onClick and onBlur fire at the same time.
Hello, Jason,
Thank you for the clarification.
For the set and now buttons I can suggest the following:
- Close the DateTimePicker when the value is changed(clicking the now and set buttons).
- Add a flag to see if the value was just changed, as otherwise, this will trigger a focus on the input, that will open the DateTimePicker again:
https://stackblitz.com/edit/react-rps4zt-uq9mkx?file=app%2Fmain.jsx
As for the cancel button, I can suggest voting for this feature, as it will allow using a custom button and controlling what its click event is doing:
https://feedback.telerik.com/kendo-react-ui/1446512-cancel-button-on-datetimepicker-render-prop
Still, I can suggest using the focus and blue logic only to control the clear button, instead of controlling the component open and closed state.
Regards,
Stefan
Progress Telerik