Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent auto focus of a material-ui popover element

I am attempting to create a search match list that updates as the user types in their query. However, I can't figure out how to maintain focus on the input element. The pop-up always gets focussed. I have tried programmatically setting the focus using refs but I cannot give a stateless function component (I'm assuming this is my TextField input) a ref.

Here is a gif of the behavior. https://imgur.com/a/JVskedr

Notice how the popup steals focus and prevents the user from typing further.

<TextField
              id='contact'
              label='Contact Name'
              className={classes.textField}
              margin='normal'
              ref={this.nameInput}
              onChange={this.handleContactSearch.bind(this)}
              value={this.state.contactSearch}
            />
            <Popover
              open={Boolean(anchorEl)}
              anchorEl={anchorEl}
              onClick={this.handlePopoverClose}
              anchorOrigin={{
                vertical: 'bottom',
                horizontal: 'center'
              }}
              transformOrigin={{
                vertical: 'top',
                horizontal: 'center'
              }}
              autoFocus={false}
            >
              <List>{this.createContactList()}</List>
            </Popover>

These are the related functions:

  handleContactSearch(event) {
    this.handlePopoverClick(event);
    this.setState({ contactSearch: handleText(event) });
    this.props.filterContacts(
      event.target.value,
      this.props.accountInfo.AccountName
    );
  }
  handlePopoverClick = event => {
    this.setState({
      anchorEl: event.currentTarget
    });
  };

  handlePopoverClose = () => {
    this.setState({
      anchorEl: null
    });
  };

How can I make the TextField element maintain focus so a user can type their query without interruption?

Sandbox: https://codesandbox.io/s/mjqoj9lxkj

like image 712
Chris Voss Avatar asked Jul 17 '18 18:07

Chris Voss


2 Answers

Pass 'disableAutoFocus', 'disableEnforceFocus' props to your popover. It worked for me!

<Popover
 open={Boolean(anchorEl)}

 // pass these props to the popover component
 disableAutoFocus={true}
 disableEnforceFocus={true}
 >

https://material-ui.com/api/modal/

like image 116
nymphadora Avatar answered Nov 06 '22 11:11

nymphadora


The reason why this is happening is that you are calling this.showPopover(event) every time the onChange={this.handleContactSearch.bind(this)} event is fired in your <TextField>.

In order to fix this, you'll need to find a way to call this.showPopover(event) only once.

I was able to make it work using a combination of autoFocus={true} and the onFocus={this.showPopover} event on the <TextField/>. The only issue with this is that the popover will show up empty when you first open the modal. I used a ref on the textfield and a conditional to set the opacity of the popover so it only shows once there's a value in the textfield.

Maybe not the ultimate solution, but it works and should at least send you in the right direction.

<div className={classes.paper}>
    <TextField
        id="contact123"
        label="Contact Name"
        className={classes.textField}
        margin="normal"
        onChange={this.handleContactSearch.bind(this)}
        value={this.state.contactSearch}
        autoFocus={true}
        onFocus={this.showPopover}
        inputRef={input => (this.tf = input)}
    />
    <Popover
        open={Boolean(anchorEl)}
        anchorEl={document.getElementById("contact123")}
        onClick={this.closePopover}
        anchorOrigin={{
            vertical: "bottom",
            horizontal: "center"
        }}
        transformOrigin={{
            vertical: "top",
            horizontal: "center"
        }}
        style={{ opacity: this.tf && !this.tf.value.length ? 0 : 1 }}
    >
        <List>{this.state.contactSearch}</List>
    </Popover>
    <div>
        <Button color="primary" className={classes.saveButton}>
            Save
        </Button>
    </div>
</div>

Sandbox: Working Demo

like image 5
CaseyC Avatar answered Nov 06 '22 10:11

CaseyC