ReactJS多选过滤器,用OR代替AND

时间:2018-10-23 13:18:36

标签: reactjs

我对所有使用ReactJS的东西都有疑问。

我有一个输入字段,可以用来过滤城市,然后结果显示为表格行。

使用以下代码:

// TODO: refactor DropDowns to module
const cityDrop = () => {
  const c = _.map(data, 'cities');
  const str = c.toString();
  const cts = str.split(',')
  const cities = _.uniqBy(cts);
  return (
    <Select
      onChange={entry => {
        this.setState({ cityValues: entry });
        this.onFilteredChangeCustom(
          entry.map(o => {
            return o.value;
          }),
          'cityTitle'
        );
      }}
      value={this.state.cityValues}
      isMulti
      className="jobs-multi-select"
      classNamePrefix="wbq-select"
      options={cities.map((o, i) => {
        return { id: i, value: o, label: o };
      })}
    />
  )
}

const positionDrop = () => {
  const allPositions = _.map(data, 'positionType.title');
  const positionsUnique = _.uniqBy(allPositions);
  return (
    <Select
      onChange={entry => {
        this.setState({ positionValues: entry });
        this.onFilteredChangeCustom(
          entry.map(o => {
            return o.value;
          }),
          'positionType'
        );
      }}
      value={this.state.positionValues}
      isMulti
      className="jobs-multi-select"
      classNamePrefix="wbq-select"
      options={positionsUnique.map((o, i) => {
        return { id: i, value: o, label: o };
      })}
    />
  )
}

const sectionDrop = () => {
  const allSections = _.map(data, 'instance.name');
  const sectionsUnique = _.uniqBy(allSections);
  return (
    <Select
      onChange={entry => {
        this.setState({ sectionValues: entry });
        this.onFilteredChangeCustom(
          entry.map(o => {
            return o.value;
          }),
          'section'
        );
      }}
      value={this.state.sectionValues}
      isMulti
      className="jobs-multi-select"
      classNamePrefix="wbq-select"
      options={sectionsUnique.map((o, i) => {
        return { id: i, value: o, label: o };
      })}
    />
  )
}


// check sort state to render a desc / asc / neutral icon
const sortState = this.state.sorted[0];
const renderSortIcon = (name) => {
  const neutralSortIcon = <svg height="10" viewBox="0 0 8 10" width="8" xmlns="http://www.w3.org/2000/svg"><g fill="none"><path d="m8 6-4 4-4-4z" fill="#d2d2d2" /><path d="m0 4 4-4 4 4z" fill="#d2d2d2" /></g></svg>;
  const descSortIcon = <svg height="10" viewBox="0 0 8 10" width="8" xmlns="http://www.w3.org/2000/svg"><g fill="none"><path d="m8 6-4 4-4-4z" fill="#d2d2d2" /><path d="m0 4 4-4 4 4z" fill="#666" /></g></svg>;
  const ascSortIcon = <svg height="10" viewBox="0 0 8 10" width="8" xmlns="http://www.w3.org/2000/svg"><g fill="none"><path d="m8 6-4 4-4-4z" fill="#666" /><path d="m0 4 4-4 4 4z" fill="#d2d2d2" /></g></svg>;
  let icon;
  if (sortState.id === name && sortState.desc) {
    icon = descSortIcon
  } else if (sortState.id === name && !sortState.desc) {
    icon = ascSortIcon
  } else if (sortState.id !== name) {
    icon = neutralSortIcon
  }
  return icon
}

// column definition for react-table
// TODO: implement multilang vars
const columns = [{
  id: 'jobTitle',
  Header: () => <div>Titel {renderSortIcon('jobTitle')}</div>,
  accessor: 'title',
  filterMethod: (filter, rows) => matchSorter(rows, filter.value, { keys: ['jobTitle'], threshold: matchSorter.rankings.WORD_STARTS_WITH }),
  filterAll: true,
  Filter: ({ filter, onChange }) => (
    <div style={{ position: 'relative' }}>
      <input
        type="text"
        className="wbqfilter"
        placeholder="Filter Titel"
        value={filter ? filter.value : ''}
        onChange={event => onChange(event.target.value)}
      />
      {/* <div className="clearInput" role="button" tabIndex={0} onClick={clearFilter} onKeyDown={clearFilter}><span></span><span></span></div> */}
    </div>
  ),
  Cell: row => (
    <a href={row.original.valanticurl}>
      {row.value}
    </a>
  ),
  width: 560,
  className: 'job-title-col',
}, {
  id: 'cityTitle',
  Header: () => <div>Standort {renderSortIcon('cityTitle')}</div>,
  accessor: (d) => {
    const array = d.cities.split(',');
    const cleanedArray = _.uniqBy(array);
    const str = cleanedArray.toString();
    const renderCities = str.replace(/,/g, ', ');
    return (
      renderCities
    )
  },
  filterMethod: (filter, renderCities) => matchSorter(renderCities, filter.value, { keys: ['cityTitle'] }),
  filterAll: true,
  Filter: () => (
    <div style={{ position: 'relative' }}>
      {cityDrop()}
    </div>
  ),
  Cell: (row) => {
    return (
      <span>
        <svg height="20" viewBox="0 0 14 20" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m12 2c-3.87 0-7 3.13-7 7 0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z" fill="#bbb" transform="translate(-5 -2)" /></svg>
        <span>
          {row.value}
        </span>
      </span>
    )
  },
  className: 'city-col',
}, {
  id: 'positionType',
  Header: () => <div>Position {renderSortIcon('positionType')}</div>,
  accessor: d => d.positionType.title,
  filterMethod: (filter, rows) => matchSorter(rows, filter.value, { keys: ['positionType'] }),
  filterAll: true,
  Filter: () => (
    <div style={{ position: 'relative' }}>
      {positionDrop()}
    </div>
  ),
  className: 'position-col',
  width: 150,
}, {
  id: 'section',
  Header: () => <div>Sektion {renderSortIcon('section')}</div>,
  accessor: d => d.instance.name,
  filterMethod: (filter, rows) => matchSorter(rows, filter.value, { keys: ['section'] }),
  filterAll: true,
  Filter: () => (
    <div style={{ position: 'relative' }}>
      {sectionDrop()}
    </div>
  ),
  className: 'section-col',
}]

if (error) {
  return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
  return <div>Loading...</div>;
} else {
  const buttonsClass = `filterBtns ${filterActive}`;
  return (
    <div>
      <div className={buttonsClass}>
        {btn('Alle', this.resetFilter)}
        {btn('Business', this.businessFilter)}
        {btn('Creative', this.creativeFilter)}
        {btn('Technology', this.techFilter)}
      </div>
      <ReactTable
        // eslint-disable-next-line
        ref={(el) => {
          this.tableInstance = el;
        }}
        data={data}
        columns={columns}
        showPagination={false}
        defaultPageSize={10}
        pageSize={data.length}
        filtered={this.state.filtered}
        sorted={this.state.sorted}
        onFilteredChange={(filtered, column, value) => {
          this.onFilteredChangeCustom(value, column.id || column.accessor);
        }}
        defaultFilterMethod={(filter, row) => {
          const id = filter.pivotId || filter.id;
          if (typeof filter.value === 'object') {
            return row[id] !== undefined
              ? filter.value.indexOf(row[id]) > -1
              : true;
          } else {
            return row[id] !== undefined
              ? String(row[id]).indexOf(filter.value) > -1
              : true;
          }
        }}
        onSortedChange={sorted => this.setState({ sorted })}
        collapseOnSortingChange
        filterable
      />
    </div>
  );
}}}

目前,该选项可与“ AND”一起使用。我希望将其与“ OR”一起使用。例如,我给城市苏黎世,慕尼黑,柏林,等等,结果用“或”代替“与”显示给我。有可能吗?

0 个答案:

没有答案