在保持过滤器的同时反应选择清除值

时间:2017-04-20 11:11:52

标签: javascript reactjs react-select

我正在开发一个权限系统,让用户可以控制谁可以访问/评论/编辑资源,就像您在Google云端硬盘上找到的一样。我正在使用React-Select multi来让资源的所有者选择他想要访问资源的用户。

当我点击react-select显示的选项时,我希望将此选项添加到允许的用户列表中(由另一个组件处理的列表)。这部分有效,我只是在select上使用了onChange处理程序(正如你在下面的代码中看到的那样)。

var language = {
   en: require(`../srv/localization/contents/entext.html`)
   ...
}

这就是我被困住的地方:一旦添加了选项,我想在搜索文本字段中的第一个选项时继续显示用户可能使用的过滤器。它现在的工作方式,过滤器被删除,所有选项都显示在下拉列表中。

使用React-Select有没有简单的方法来实现这一目标?

非常感谢!

2 个答案:

答案 0 :(得分:1)

此代码正常运行。也许有更好的方法。

// ManageUsers
import React, { PropTypes } from 'react';
import AddUserForm from './AddUserForm'

export default class NoMatch extends React.Component {
  constructor(props) {
    super(props)
    this.handleChange = this.handleChange.bind(this);

    let selectedUsers = [ { value: 3, label: 'Three' },
      { value: 4, label: 'Four' } ];

    this.state = {
      selectedUsers: selectedUsers
    }
  }

  handleChange(selected) {
    this.setState({ selectedUsers: selected })
  }

  render() {
    let usersList = [
      { value: 1, label: 'One' },
      { value: 2, label: 'Two' }
    ];

    return (
      <div>Users
        <AddUserForm usersList={usersList} 
         selectedUsers={this.state.selectedUsers} 
         handleChange={this.handleChange} />
      </div>
    );
  }
}
// AddUsersForm
import React, { PropTypes } from 'react';
import Select from 'react-select';
import 'react-select/dist/react-select.css';

export default class AddUsersForm extends React.Component {
 PropTypes = {
  usersList: PropTypes.array.isRequired,
  selectedUsers: PropTypes.array.isRequired,
  handleChange: PropTypes.func.isRequired
 }

 render() {
  return (
   <form>
    <Select
     multi={true}
     options={this.props.usersList}
     value={this.props.selectedUsers}
     onChange={(users) => this.props.handleChange(users)}
    />
   </form>
  );
 }
}

如果要保留键入的文本,则必须在handleChange上设置输入的文本。保留输入的文本没有内置功能。<​​/ p>

enter image description here

 onChange={(users) => this.props.handleChange(users, event)}
handleChange(selected, event) {
let selectedFilter = event.target;
 // then navigated to the input element with Javascript or jQuery
 // and set the value of the input

this.setState({ selectedUsers: selected })
}

答案 1 :(得分:1)

我的方式:

  1. Option组件替换为自己的组件(Material-UI库中的几个组件)。
  2. 重写的onClick事件处理程序-这是一些逻辑,并从ReactSelect道具中调用onChange处理程序。在onClick处理程序的末尾添加了event.stopPropagation()
import React from 'react';

import MenuItem from '@material-ui/core/MenuItem/MenuItem';
import Checkbox from '@material-ui/core/Checkbox/Checkbox';
import ListItemText from '@material-ui/core/ListItemText/ListItemText';

const MultiOption = props => (
  <MenuItem
    buttonRef={props.innerRef}
    {...props.innerProps}
    onClick={event => {
      let values = [];
      if (props.isSelected) {
        values = props.selectProps.value.filter(
          item => item.value !== props.value,
        );
      } else {
        values = [props.data].concat(props.selectProps.value);
      }
      props.selectProps.onChange(values);
      event.stopPropagation();
    }}
    style={{
      overflow: 'initial',
      padding: 0,
    }}
  >
    <Checkbox
      checked={props.isSelected}
      style={{
        padding: 4,
      }}
    />
    <ListItemText
      primary={props.label}
      classes={{
        root: props.selectProps.classes.optionRoot,
      }}
    />
  </MenuItem>
);

export default MultiOption;
import React from 'react';
import PropTypes from 'prop-types';
import Select from 'react-select';

import { withStyles } from '@material-ui/core/styles';

import { getComponents } from './components';

import { styles, getSelectStyles } from './styles';

class Combobox extends React.Component {
  handleChange = () => value => {
    const { onChange } = this.props;
    onChange(value);
  };

  render() {
    const {
      classes,
      theme,
      options,
      label,
      rootStyle,
      value,
      error,
      isInner,
      isMulti,
      fullWidth,
      ...props
    } = this.props;

    return (
      <div className={classes.root} style={{ ...rootStyle }}>
        <Select
          {...props}
          isClearable
          classes={classes}
          styles={getSelectStyles({
            theme,
            fullWidth,
          })}
          options={options}
          menuPortalTarget={document.body}
          menuPlacement="auto"
          value={value || null}
          onChange={this.handleChange()}
          components={getComponents({
            isInner,
            isMulti,
          })}
          textFieldProps={{
            label,
            error: !!error,
            helperText: error,
            InputLabelProps: { shrink: true },
          }}
          isMulti={isMulti}
          hideSelectedOptions={!isMulti}
          closeMenuOnSelect={!isMulti}
          loadingMessage={() => 'Loading...'}
        />
      </div>
    );
  }
}

Combobox.propTypes = {
  options: PropTypes.arrayOf(PropTypes.shape({})),
  label: PropTypes.string,
  classes: PropTypes.shape({}).isRequired,
  theme: PropTypes.shape({}).isRequired,
  value: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
    PropTypes.bool,
    PropTypes.arrayOf(PropTypes.any),
    PropTypes.shape({}),
  ]),
  error: PropTypes.string,
  onChange: PropTypes.func.isRequired,
  isInner: PropTypes.bool,
  isMulti: PropTypes.bool,
  fullWidth: PropTypes.bool,
};

Combobox.defaultProps = {
  options: [],
  label: '',
  value: null,
  error: '',
  isInner: false,
  isMulti: false,
  fullWidth: false,
};

export default withStyles(styles, { withTheme: true })(({ ...props }) => (
  <Combobox {...props} />
));
import Control from './Control';
import InnerControl from './InnerControl';

import InputComponent from './InputComponent';
import MenuList from './MenuList';

import Option from './Option';
import MultiOption from './MultiOption';

import SingleValue from './SingleValue';
import MultiValue from './MultiValue';

import NoOptionsMessage from './NoOptionsMessage';

import Placeholder from './Placeholder';

import ValueContainer from './ValueContainer';

const getComponents = ({ isInner, isMulti }) => ({
  Control: isInner ? InnerControl : Control,
  ...(isMulti && { MenuList }),
  MultiValue,
  NoOptionsMessage,
  Option: isMulti ? MultiOption : Option,
  Placeholder,
  SingleValue,
  ValueContainer,
});

export {
  Control,
  InnerControl,
  InputComponent,
  MenuList,
  Option,
  MultiOption,
  SingleValue,
  MultiValue,
  NoOptionsMessage,
  Placeholder,
  ValueContainer,
  getComponents,
};