Onlyann
Onlyann

Reputation: 335

How to prevent Office UI Fabric React DatePicker flyout from stealing focus when allowTextInput is true?

When using the DatePicker from Office UI Fabric React

<DatePicker allowTextInput /> 

the date picker flyout takes the focus and I need to click again on the date picker input to be able to enter text.

While this is the documented behaviour, I would like to know if there is a way to stop it from happening.

Two acceptable alternatives would be, by order of preference to:

  1. not open the flyout when clicking on the input.
  2. open the flyout but keep the focus on the input

Ideally, there would be autoOpenOnClick flag or similar.

Upvotes: 0

Views: 2000

Answers (2)

Piotr Kątny
Piotr Kątny

Reputation: 71

If you still didn't solve the issue, try to set:

disableAutoFocus={true}

for your DatePicker.

It was fixed in this commit (Oct 23, 2019):
https://github.com/OfficeDev/office-ui-fabric-react/commit/fcbe8aca1e71114990a965a666b3c555113189d8

Upvotes: 1

mirage
mirage

Reputation: 708

There seems to be something wrong with the calendar component that makes it steal focus (the previous month button (up arrow) to be exact = first focusable element inside the callout) even though there is a calloutProp that is supposed to allow you to prevent the focus changing (checkout the _onCalloutPositioned function: https://github.com/OfficeDev/office-ui-fabric-react/blob/master/packages/office-ui-fabric-react/src/components/DatePicker/DatePicker.base.tsx#L303).

Try this out to control the focus with a little timing:

dateRef = React.createRef();

...

<div ref={this.dateRef}>
    <DatePicker
        calloutProps={{setInitialFocus: false}} // This doesn't work
        label="Start date"
        allowTextInput={true}
        value={value}
        onFocus={this.onFocus}
        {...otherDatePickerProps}
    />
</div>

...

onFocus = () => {
    let node = ReactDOM.findDOMNode(this.dateRef && this.dateRef.current && this.dateRef.current.firstChild);
    node = node && node.querySelector && node.querySelector('.ms-TextField-fieldGroup');
    node = node && node.getElementsByTagName('input');
    node = node && node.length && node[0];
    setTimeout(function(){
      node.focus();
    }, 500);
}

Basically wrap the DatePicker with a div that you can save a reference (dateRef) to and then find the input element and focus on it after a little wait (to ensure you're doing it after the Calendar is done stealing focus). You can probably prune/clean up some of the node selector logic if you want.

Upvotes: 0

Related Questions