自动建议/组合框建议不会显示

时间:2019-02-07 14:28:17

标签: reactjs components autosuggest

由于某种原因,建议不会显示,控制台中没有错误消息。

combo box flow

Senario

  1. 用户单击组合框,将显示建议。 (正在工作)

  2. 用户选择一个建议。建议显示在组合框中。 (在单个跨度中选择其加载)

  3. 如果用户在选择后单击组合框,则组合框将清除值,但先前的选择将显示为突出显示的第一选择。还在第一选择下方更新了建议显示。 (我确实需要这方面的帮助,我可以在控制台日志中看到数据。但是由于没有显示建议,所以我可以判断其是否按要求显示)

(请参阅图片以供参考)

react-autosuggest react-autosuggest@9.3.4

组件代码

import React, { Component } from "react";
import ReactDOM, { findDOMNode } from "react-dom";
import PropTypes from "prop-types";
import classNames from "classnames";
import Autosuggest from "react-autosuggest";

import Icon from '../Components/Icons/Icons';

class Autocomplete extends Component {
  constructor() {
    super();

    this.state = {
      value: "",
      suggestions: [],
      isTouched: false,
      multi: false,
      selectedInput: ""
    };

    this.onChange = this.onChange.bind(this);
    this.onClick = this.onClick.bind(this);
    this.blurCallback = this.blurCallback.bind(this);
    this.triggerFocus = this.triggerFocus.bind(this);
    this.handleClear = this.handleClear.bind(this);
  }

  getSuggestionValue = suggestion => suggestion.text;

  renderSuggestion = suggestion => (<span>{suggestion.text}</span>)

  escapeRegexCharacters = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");

  getSectionSuggestions = section => section && section.items;

  getSuggestions = (value, selected, reason) => {
    let suggestions = this.props.data;

    if (value !== undefined) {
      const escapedValue = this.escapeRegexCharacters(value.trim());
      const selectedInput = [];
      selectedInput.push(selected);
      const regex = new RegExp(escapedValue, "i");
      const filtered = suggestions.filter(language =>
        regex.test(language.text)
      );

      if (escapedValue === "") {
        return {
          suggestions: [
            { text: selectedInput[0], items: [] },
            { text: "", items: filtered }
          ],
          multi: true
        };
      }

      if (!filtered.length) {
        return {
          suggestions: selectedInput.length > 0 ? selectedInput : filtered,
          multi: false
        };
      }

      return {
        suggestions: [{
            text: selectedInput[0],
            items: selectedInput.length > 0 ? selectedInput : filtered
          },
          {
            text: "",
            items: reason === "focused" ? suggestions : filtered
          }],
        multi: true
      };
    } else return;
  };

  onSuggestionsFetchRequested = ({ value, reason }) => {
    if (reason === "input-focused") {
      this.setState({ value: "" });
      const { multi, suggestions } = this.getSuggestions(
        value,
        this.state.selectedInput ? this.state.selectedInput : "",
        "focused"
      );
      this.setState({
        suggestions,
        multi
      });
    } else {
      const { multi, suggestions } = this.getSuggestions(
        value,
        this.state.selectedInput ? this.state.selectedInput : "",
        "notfocused"
      );
      this.setState({
        suggestions,
        multi
      });
    }
  };

  onSuggestionsClearRequested = () => {
    this.setState({
      suggestions: [],
      multi: false
    });
  };

  onChange = (event, { newValue, method }) => {
    if (method === "enter") {
      this.setState({
        value: this.state.value
      });
    } else {
      this.setState({
        value: newValue
      });
    }

    if(this.props.search) {
      this.props.search(newValue, ReactDOM.findDOMNode(this).parentNode.parentNode.querySelectorAll('li'));
    };
  };

  onSuggestionSelected = (ev,
    { suggestion, suggestionValue, suggestionIndex, sectionIndex, method }
  ) => {
    this.setState({
      selectedInput: suggestionValue
    });
  };

  blurCallback (ev) {
    this.setState({  isTouched: false });
  }

  handleClear() {
    this.setState({
      value: ''
    })
  }
  onClick(ev) {
    this.setState({ isTouched: true });
  }

  triggerFocus() {
    const input = document.getElementById(this.props.id);
    input.focus();
  }

  render() {

    const theme = {
      container: "el-form",
      containerOpen: "react-autosuggest__container--open",
      input: "autocomplete form-control",
      inputOpen: "react-autosuggest__input--open",
      inputFocused: "react-autosuggest__input--focused",
      suggestionsContainer: "react-autosuggest__suggestions-container",
      suggestionsContainerOpen:
        "react-autosuggest__suggestions-container--open",
      suggestionsList: "autocomplete-wrap",
      suggestion: "react-autosuggest__suggestion",
      suggestionFirst: "react-autosuggest__suggestion--first",
      suggestionHighlighted: "react-autosuggest__suggestion--highlighted",
      sectionContainer: "react-autosuggest__section-container",
      sectionContainerFirst: "react-autosuggest__section-container--first",
      sectionTitle: "react-autosuggest__section-title"
    };

    const {
      className,
      placeholder,
      data,
      disabled,
      label,
      labelClass,
      icon,
      iconSize,
      iconClass,
      clear,
      clearClass,
      id,
      search,
      ...attributes
    } = this.props;

    const labelClassFix = classNames(
      isNotEmpty && "active",
      disabled && "disabled",
      labelClass
    );
    const iconClassFix = classNames(
      "prefix",
      this.state.isTouched && "active",
      iconClass
    );
    const clearClassFix = classNames(
      clearClass
    )

    const isclearVisible = () => {
      let hiddenOrNot = "hidden"
      if (this.state.value) {
        hiddenOrNot = "visible";
      }
      return hiddenOrNot;
    }
    const clearStyleFix = {
      position: "absolute",
      zIndex: 2,
      top: "2.5rem",
      right: "10px",
      border: "none",
      background: "0 0",
      visibility: isclearVisible(),
    }

    let isNotEmpty =
      Boolean(this.state.value) || placeholder || this.state.isTouched;

    const { value, suggestions, multi } = this.state;

    const inputProps = {
      placeholder: placeholder,
      value,
      onChange: this.onChange,
      onBlur: this.blurCallback,
      onClick: this.onClick,
      onFocus: this.onFocus,
      id: this.props.id,
      name: this.props.name
    };

    const renderInputComponent = inputProps => (
      <div>
        { icon && <Icon icon={icon} className={iconClassFix}/> }
        <input
          type="text"
          id={id}
          name={name}
          className="form-control"
          {...inputProps}
          onFocus={(ev, val) => {
            this.onClick();
            inputProps.onFocus(ev, val);
          }}
        />
        <label
          htmlFor={id}
          id={`label for ${id}`}
          onClick={this.triggerFocus}
          className={labelClassFix}
        >
          { label }
        </label>
        { clear &&
          <Icon icon="close" onClick={this.handleClear} style={clearStyleFix}
          className={clearClassFix}/>
        }
      </div>
    );

    return (
        <Autosuggest
          multiSection={multi}
          renderSectionTitle={this.renderSuggestion}
          getSectionSuggestions={this.getSectionSuggestions}
          suggestions={suggestions}
          highlightFirstSuggestion={true}
          focusInputOnSuggestionClick={false}
          onSuggestionsClearRequested={this.onSuggestionsClearRequested}
          onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
          getSuggestionValue={this.getSuggestionValue}
          renderSuggestion={this.renderSuggestion}
          inputProps={inputProps}
          theme={theme}
          renderInputComponent={renderInputComponent}
          shouldRenderSuggestions={ () => true }
          onSuggestionSelected={this.onSuggestionSelected}
        />
    );
  }
}

Autocomplete.propTypes = {
  className: PropTypes.string,
  icon: PropTypes.string,
  id: PropTypes.string,
  name: PropTypes.string,
};

Autocomplete.defaultProps = {
  id: 'autocomplete-1',
  name: '',
  clear: true
};

export default Autocomplete;

使用中的组件

const states = [ "Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illnois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming" ];

<Autocomplete
  data={states}
  label="Choose your state"
  icon="lightbulb"
  clear
  clearClass="grey-text" id="combobox-states" name="state-selection"
  className="mx-auto"
/>

Codesandbox

1 个答案:

答案 0 :(得分:0)

在某些回调中您需要一个return

  getSuggestionValue = suggestion => {
    return suggestion;
  }

  getSectionSuggestions = (section) => {
    return section && section.items;
  }

编辑

getSuggestions中,您需要直接返回一个数组,而不是一个对象。 参见https://codesandbox.io/s/w04jpzjr4k