简体   繁体   中英

React-Bootstrap Dropdown with Input won't stay open

I am using React-Bootstrap DropDown with an Input inside a MenuItem (otherwise the console yells at me Uncaught TypeError: Cannot read property 'focus' of undefined )

Okay so the drop down renders, and the input is inside a menu item (all is well) except when I click inside the input, the dropdown closes.

Here is my JSX

<Bootstrap.DropdownButton title={this.state.callIdTitle} id="callId">
  <Bootstrap.MenuItem eventKey='1'>
   <input ref="callIdInput" type='text' eventKey='2' placeholder='Enter Call ID' />
  </Bootstrap.MenuItem>
</Bootstrap.DropdownButton>

Any pointing in the right direction is very much appreciated, I have been trying to solve this all day.

Thank you.

I managed to get it working by having a custom onToggle for dropdown that does nothing if click comes from input element. I basically ended up with something like this:

So something like this:

var React = require('react');

var ReactBootstrap = require('react-bootstrap'),
    Dropdown = ReactBootstrap.Dropdown,
    DropdownToggle = Dropdown.Toggle,
    DropdownMenu = Dropdown.Menu,
    Input = ReactBootstrap.Input,
    MenuItem = ReactBootstrap.MenuItem;

module.exports = React.createClass({
  displayName: 'DropdownWithInput',

  setValue: function(e) {
    var value = e.target.value;

    this.setState({value: value});
  },

  onSelect: function(event, value) {
    this.setState({value: value});
  },

  inputWasClicked: function() {
    this._inputWasClicked = true;
  },

  onToggle: function(open) {
    if (this._inputWasClicked) {
      this._inputWasClicked = false;
      return;
    }
    this.setState({open: open});
  },

  render: function() {
    return (
        <Dropdown id={this.props.id} open={this.state.open} onToggle={this.onToggle}
                  className="btn-group-xs btn-group-default">
          <DropdownToggle bsStyle="default" bsSize="xs" className="dropdown-with-input dropdown-toggle">
            Dropdown with input
          </DropdownToggle>

          <DropdownMenu>
            <Input
                type="text"
                ref="inputElem"
                autoComplete="off"
                name={this.props.name}
                placeholder="Type something here"
                onSelect={this.inputWasClicked}
                onChange={this.setValue}
                />
            <MenuItem divider key={this.props.id + '-dropdown-input-divider'}/>
            <MenuItem eventKey={1} onSelect={this.onSelect}>One</MenuItem>
            <MenuItem eventKey={2} onSelect={this.onSelect}>Two</MenuItem>
            <MenuItem eventKey={3} onSelect={this.onSelect}>Three</MenuItem>
          </DropdownMenu>
        </Dropdown>
    );
  }

});

Hope this works for you as well.

This capability is a relatively new feature for React-Bootstrap. Checkout the newer Dropdown Customization docs: http://react-bootstrap.github.io/components.html#btn-dropdowns-custom The last example of that section includes a dropdown with an input. The dropdown trigger looks like a link there, but you can also customize that.

I found a solution to this issue that worked pretty well for me. Inside the dropdown menu I had aa text input ( not inside of a MenuItem).

<input onSelect={e => e.stopPropagation()} ... />

After all day...this is what I came up with.

I hope there's a better way.

    <Bootstrap.DropdownButton onClick={this.setFocusToCallIdInput} title={this.state.callIdTitle}>
      <Bootstrap.MenuItem href="javascript:void(0);" eventKey='1'>
        <Bootstrap.Input onClick={this.dontCloseMeBro} ref="callIdInput" type='text' onChange={this.callIdInputSelected} placeholder='Enter Call ID' />
      </Bootstrap.MenuItem>
    </Bootstrap.DropdownButton>



setFocusToCallIdInput:function(e){
    console.log("Call Id clicked");     
    React.findDOMNode(this.refs.callIdInput).focus();
    e.stopPropagation();
    e.nativeEvent.stopImmediatePropagation();
},
dontCloseMeBro:function(e){
    console.log("menu item clicked");       
    React.findDOMNode(this.refs.callIdInput).focus();
    e.stopPropagation();
    e.nativeEvent.stopImmediatePropagation();
},

This seems to be working for me.

<Dropdown id="my-dropdown">
  <Input 
    type="text"
    bsRole="toggle"
    value={this.state.inputValue}
    onChange={this.onChange} />
  <Dropdown.Menu>
    <MenuItem key={1}>Item 1</MenuItem>
    <MenuItem key={2}>Item 2</MenuItem>
    <MenuItem key={3}>Item 3</MenuItem>
  </Dropdown.Menu>
</Dropdown>

This is an example of a reusable function component that will stay open unless you click away from it (ie it will stay open when you type in the input). This is also useful if you have a dropdown with checkboxes inside it etc.

const StayOpenDropdown = ({ children, ...rest }) => {
    const [show, setShow] = useState(false)
    const onToggle = (isOpen, e, metadata) => {
        setShow(isOpen || metadata.source === 'select')
    }
    return (
        <DropdownButton show={show} onToggle={onToggle} {...rest}>
            {children}
        </DropdownButton>
    )
}

const MyComponent = () => (
    <StayOpenDropdown title='Some Title' >
        <input type='text' placeholder='Enter Call ID' />
    </StayOpenDropdown>
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM