首页 > 解决方案 > 使用react-input-trigger,按下@时如何显示所有选项的列表?

问题描述

我正在使用 react-input-trigger 库https://github.com/abinavseelan/react-input-trigger来实现 @mentions 功能(如 twitter)。

我想要发生的是按下“@”时显示的可用选项列表。

当前发生的情况是我必须在列表显示之前输入“@”加上一个字符。它是如此接近我需要的东西,但我一生都无法弄清楚这部分......!

这是我关于堆栈溢出的第一个问题,我非常努力地寻找这个问题的答案,但我找不到任何解决这个特定问题的方法,如果我错过了什么,我深表歉意。

我当前的代码如下所示:

import React, { Component } from 'react';
import InputTrigger from 'react-input-trigger';
import { TextArea, Dropdown, Step, H3 } from "../../styled-components/styled-components"

class CreateMessage extends Component {
    state = {
      top: null,
      left: null,
      showSuggestor: false,
      startPosition: null,
      text: null,
      currentSelection: 0,
      textareaValue: "",
      properties: [{name: "property1", type: "string"}, {name: "property2", type: "string"}, {name: "property3", type: "string"}, {name: "property4", type: "string"}]
    }

  toggleSuggestor = (metaInformation) => {
    const { hookType, cursor } = metaInformation;

    if (hookType === 'start') {
      this.setState({
        showSuggestor: true,
        left: cursor.left,
        top: cursor.top + 20, 
        startPosition: cursor.selectionStart,
      });
    }

    if (hookType === 'cancel') {
      this.setState({
        showSuggestor: false,
        left: null,
        top: null,
        text: null,
        startPosition: null,
      });
    }
  }

  handleInput = (metaInformation) => {
    this.setState({ text: metaInformation.text });
  }

  handleKeyDown = (event) => {
    const { which } = event;
    const { currentSelection } = this.state;
    const keyInputs = {
      down: 40,
      up: 38,
      enter: 13
    }
    let properties = this.state.properties.map(( p ) => p)

    if (which === keyInputs.down ) { 
      event.preventDefault();
      this.setState({
        currentSelection: (currentSelection + 1) % properties.length,
      });
    }

    if (which === keyInputs.up ) { // 40 is the character code of the up arrow
      event.preventDefault();
      this.setState({
        currentSelection: (currentSelection - 1) % properties.length,
      });
    }

    if (which === keyInputs.enter) { // 13 is the character code for enter
      event.preventDefault();
      const { currentSelection, startPosition, textareaValue } = this.state;
      const property = properties[currentSelection];
      const newText = `${textareaValue.slice(0, startPosition - 1)}{ ${property.name} }${textareaValue.slice(startPosition + property.name.length, textareaValue.length)}`

      this.setState({
        showSuggestor: false,
        left: null,
        top: null,
        text: null,
        startPosition: null,
        textareaValue: newText,
      });

      this.endHandler();
    }
  }

  handleTextareaInput = (event) => {
    const { value } = event.target;
    this.setState({ textareaValue: value })
  }


  render() {    
    let properties = this.state.properties.map(( p ) => p )

    return (
      <Step>
        <H3>Enter Message:</H3>
        <div style={{ position: 'relative' }} id="message-container" onKeyDown={this.handleKeyDown}>
          <InputTrigger
            trigger={{ keyCode: 50, shiftKey: true }}
            onStart={(metaData) => { this.toggleSuggestor(metaData); }}
            onCancel={(metaData) => { this.toggleSuggestor(metaData); }}
            onType={(metaData) => { this.handleInput(metaData); }}
            endTrigger={(endHandler) => { this.endHandler = endHandler; }}
          >
            <TextArea id="event-message" onChange={this.handleTextareaInput} value={this.state.textareaValue} />
          </InputTrigger>

          <Dropdown id="dropdown" style={{ display: this.state.showSuggestor ? "block" : "none", top: this.state.top, left: this.state.left }}>
            {
              properties
                .filter(property => property.name.indexOf(this.state.text) !== -1)
                .map((property, index) => (
                  <div
                    key={index}
                    className='dropdown-item'
                    style={{ padding: '10px 20px', background: index === this.state.currentSelection ? '#eee' : '' }}
                  >
                    { property.name }
                  </div>
                ))  
            }
          </Dropdown>
        </div>
      </Step>
    );
  }  
}

export default CreateMessage;

标签: javascriptreactjs

解决方案


推荐阅读