要向“蓝图选择”组件弹出框添加元素吗?

时间:2018-09-01 16:44:00

标签: reactjs drop-down-menu blueprintjs

Blueprint的Select组件正是我当前的React项目所需的组件,但有一个例外:我需要在其弹出框中添加一些元素,但看不到任何实现方法。

具体来说,我想在过滤器输入上方添加标题(例如H2元素),并在列表下方添加按钮栏(例如DIV中的某些Button组件)。 Select似乎具有很高的可配置性,但是我看不到在弹出框内添加元素的方法……我缺少什么?

2 个答案:

答案 0 :(得分:1)

如果要扩展选择的菜单并向其中添加自定义元素,则必须提供itemListRenderer道具。

Here's what the docs says

  

默认情况下,“选择”呈现菜单中显示的项目。这个   行为可以通过提供 itemListRenderer 道具来覆盖,   让您完全控制项目的布局。例如你   可以将项目归为一个共同的标题,或呈现大型数据集   使用react-virtualized。

itemListRenderer 示例:

  

如果提供,则将调用itemListRenderer属性以呈现下拉菜单的内容。它可以访问项目,当前查询以及用于渲染单个项目的renderItem回调。还提供了一个引用处理程序(itemsParentRef);应该将其附加到呈现的菜单项的父元素上,以便当前选择的项可以自动滚动到视图中。

因此,在Menu组件的正文中,您可以放置​​自定义标题和按钮:

import { ItemListRenderer } from "@blueprintjs/select";

const renderMenu: ItemListRenderer<Film> = ({ items, itemsParentRef, query, renderItem }) => {
    const renderedItems = items.map(renderItem).filter(item => item != null);
    return (
        <Menu ulRef={itemsParentRef}>
            <h2>Your heading can be styled here</h2>
            <MenuItem
                disabled={true}
                text={`Found ${renderedItems.length} items matching "${query}"`}
            />
            {renderedItems}
            <div>
              <button>Button name</button>
            </div>
        </Menu>
    );
};

<FilmSelect
    itemListRenderer={renderMenu}
    itemPredicate={filterFilm}
    itemRenderer={renderFilm}
    items={...}
    onItemSelect={...}
/>

答案 1 :(得分:1)

Jordan的上述建议,加上一些实验,最终得出了可行的答案:

  1. filterable设置为false可隐藏内置过滤器输入。
  2. 使用itemListRenderer不仅可以显示下拉菜单项,还可以使用InputGroup来代替替换过滤器。
  3. 使用InputGroup的inputRef属性来捕获对基础HTML输入的引用。通过Select的onOpening道具的popoverProps属性,使用它来集中显示输入内容。

这是实现上述内容的简单组件:

// Extends Blueprint's Select component with header and footer props that
// can be any arbitrary elements or components
class ExtendedSelect extends Component {
  constructor(props) {
    super(props);
    this.inputRef = null;
    this.state = {query: ""};
  }

  handleInputChanged = event => {
    this.setState({query: event.target.value});
  }

  receiveInputRef = (ref) => {
    this.inputRef = ref;
  }

  handlePopoverOpening = () => {
    if (this.inputRef) {
      this.inputRef.focus();
    }
  }

  listRenderer = ({filteredItems, renderItem}) => {
    // Apply the supplied item renderer to the filtered list of items
    const renderedItems = filteredItems.map(renderItem);

    return (
      <div>
        {this.props.header}
        <InputGroup inputRef={this.receiveInputRef} value={this.state.query} onChange={this.handleInputChanged} leftIcon="search" />
        <Menu>
          {renderedItems}
        </Menu>
        {this.props.footer}
      </div>
    );
  }

  render() {
    return (
        <Select
          items={this.props.items}
          filterable={false}
          query={this.state.query}
          itemListRenderer={this.listRenderer}
          itemPredicate={this.props.itemPredicate}
          itemRenderer={this.props.itemRenderer}
          popoverProps={{onOpening:this.handlePopoverOpening}}
          onItemSelect={this.props.onItemSelect}
          >

          {this.props.children}
        </Select>
    );
  }
}

(请注意,我只是将Select的一些道具传递给自定义组件,如果我是经验丰富的React开发人员,我想我会知道一种将所有道具传递给别人的方法。)

这出乎意料地很好-例如,除了在输入时进行一些使焦点集中的工作之外,Select的所有其他内置行为都可以按预期工作,例如在焦点对准输入时菜单的键盘导航。