Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "office-ui-fabric-react",
"comment": "Pickers: Fix focus problems and scroll issues",
"type": "patch"
}
],
"packageName": "office-ui-fabric-react",
"email": "joschect@microsoft.com"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import {
BaseComponent,
KeyCodes,
css,
createRef
createRef,
elementContains
} from '../../Utilities';
import { FocusZone, FocusZoneDirection } from '../../FocusZone';
import { Callout, DirectionalHint } from '../../Callout';
Expand Down Expand Up @@ -417,30 +418,38 @@ export class BasePicker<T, P extends IBasePickerProps<T>> extends BaseComponent<
}

protected onInputFocus = (ev: React.FocusEvent<HTMLInputElement | Autofill>): void => {
this.setState({ isFocused: true });
this.selection.setAllSelected(false);
if (this.input.value && this.input.value.value === '' && this.props.onEmptyInputFocus) {
this.onEmptyInputFocus();
this.setState({
isMostRecentlyUsedVisible: true,
moreSuggestionsAvailable: false,
suggestionsVisible: true
});
} else if (this.input.value && this.input.value.value) {
this.setState({
isMostRecentlyUsedVisible: false,
suggestionsVisible: true
});
}
if (this.props.inputProps && this.props.inputProps.onFocus) {
this.props.inputProps.onFocus(ev as React.FocusEvent<HTMLInputElement>);
// Only trigger all of the focus if this component isn't already focused.
// For example when an item is selected or removed from the selected list it should be treated
// as though the input is still focused.
if (!this.state.isFocused) {
this.setState({ isFocused: true });
this.selection.setAllSelected(false);
if (this.input.value && this.input.value.value === '' && this.props.onEmptyInputFocus) {
this.onEmptyInputFocus();
this.setState({
isMostRecentlyUsedVisible: true,
moreSuggestionsAvailable: false,
suggestionsVisible: true
});
} else if (this.input.value && this.input.value.value) {
this.setState({
isMostRecentlyUsedVisible: false,
suggestionsVisible: true
});
}
if (this.props.inputProps && this.props.inputProps.onFocus) {
this.props.inputProps.onFocus(ev as React.FocusEvent<HTMLInputElement>);
}
}
}

protected onInputBlur = (ev: React.FocusEvent<HTMLInputElement | Autofill>): void => {
this.setState({ isFocused: false });
if (this.props.inputProps && this.props.inputProps.onBlur) {
this.props.inputProps.onBlur(ev as React.FocusEvent<HTMLInputElement>);
// Only blur if an unrelated element gets focus. Otherwise treat it as though it still has focus.
if (!elementContains(this.root.value!, ev.relatedTarget as HTMLElement)) {
this.setState({ isFocused: false });
if (this.props.inputProps && this.props.inputProps.onBlur) {
this.props.inputProps.onBlur(ev as React.FocusEvent<HTMLInputElement>);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,25 @@ export class Suggestions<T> extends BaseComponent<ISuggestionsProps<T>, ISuggest
protected _searchForMoreButton = createRef<IButton>();
protected _selectedElement = createRef<HTMLDivElement>();
private SuggestionsItemOfProperType = SuggestionsItem as new (props: ISuggestionItemProps<T>) => SuggestionsItem<T>;

private activeSelectedElement: HTMLDivElement | null;
constructor(suggestionsProps: ISuggestionsProps<T>) {
super(suggestionsProps);
this.state = {
selectedActionType: SuggestionActionType.none,
};
}

public componentDidUpdate() {
public componentDidMount() {
this.scrollSelected();
this.activeSelectedElement = this._selectedElement ? this._selectedElement.value : null;
}
public componentDidUpdate() {
// Only scroll to selected element if the selected element has changed. Otherwise do nothing.
// This prevents some odd behavior where scrolling the active element out of view and clicking on a selected element
// will trigger a focus event and not give the clicked element the click.
if (this.activeSelectedElement && this._selectedElement.value && this.activeSelectedElement !== this._selectedElement.value) {
this.scrollSelected();
this.activeSelectedElement = this._selectedElement.value;
}
}

public render() {
Expand Down