Draft.js - 添加未选择文本的链接

时间:2017-11-02 21:02:58

标签: draftjs

如何添加链接?我知道如何添加指向 选择

的链接
          const contentState = editorState.getCurrentContent();
          const contentStateWithEntity = contentState.createEntity(
            'LINK',
            'MUTABLE',
            {url: urlValue}
          );
          const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
          const newEditorState = EditorState.set(editorState, { currentContent: contentStateWithEntity });
          this.setState({
            editorState: RichUtils.toggleLink(
              newEditorState,
              newEditorState.getSelection(),
              entityKey
            )}

我们选择newEditorState.getSelection()并添加链接。

但如何在没有选择的情况下添加链接?如果未选择文字,只需添加带有文字的新a标记即可?如果我没有选择任何文字,它就不会添加任何内容。

2 个答案:

答案 0 :(得分:5)

您可以使用编辑器状态执行任何操作,而无需更新组件。因此,您可以添加所需的文本,然后以编程方式在此文本上设置选择,最后创建链接并更新组件。

看看这个工作示例 - https://jsfiddle.net/levsha/2op5cyxm/ 在这里,我点击按钮后添加一个链接。

handleAddLink = () => {
  const { editorState } = this.state;
  const selectionState = editorState.getSelection();
  const contentState = editorState.getCurrentContent();
  const currentBlock = contentState.getBlockForKey(selectionState.getStartKey());
  const currentBlockKey = currentBlock.getKey();
  const blockMap = contentState.getBlockMap();
  const blocksBefore = blockMap.toSeq().takeUntil((v) => (v === currentBlock));
  const blocksAfter = blockMap.toSeq().skipUntil((v) => (v === currentBlock)).rest();
  const newBlockKey = genKey();

  // add new ContentBlock to editor state with appropriate text

  const newBlock = new ContentBlock({
    key: newBlockKey,
    type: 'unstyled',
    text: linkText,
    characterList: new List(Repeat(CharacterMetadata.create(), linkText.length)),
  });

  const newBlockMap = blocksBefore.concat(
    [[currentBlockKey, currentBlock], [newBlockKey, newBlock]],
    blocksAfter
  ).toOrderedMap();

  const selection = editorState.getSelection();

  const newContent = contentState.merge({
    blockMap: newBlockMap,
    selectionBefore: selection,
    selectionAfter: selection.merge({
      anchorKey: newBlockKey,
      anchorOffset: 0,
      focusKey: newBlockKey,
      focusOffset: 0,
      isBackward: false,
    }),
  });

  let newEditorState = EditorState.push(editorState, newContent, 'split-block');

  // programmatically apply selection on this text 

  const newSelection = new SelectionState({
    anchorKey: newBlockKey,
    anchorOffset: 0,
    focusKey: newBlockKey,
    focusOffset: linkText.length
  });

  newEditorState = EditorState.forceSelection(newEditorState, newSelection);

  // create link entity

  const newContentState = newEditorState.getCurrentContent();

  const contentStateWithEntity = newContentState.createEntity(
    'LINK',
    'IMMUTABLE',
    { url: linkUrl }
  );

  const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
  newEditorState = EditorState.set(newEditorState, { currentContent: contentStateWithEntity });

  newEditorState = RichUtils.toggleLink(newEditorState, newEditorState.getSelection(), entityKey);

  // reset selection

  newSelection = new SelectionState({
    anchorKey: newBlockKey,
    anchorOffset: linkText.length,
    focusKey: newBlockKey,
    focusOffset: linkText.length
  });

  newEditorState = EditorState.forceSelection(newEditorState, newSelection);

  // update our component

  this._handleChange(newEditorState);
}

答案 1 :(得分:1)

我真正简洁的解决方案。带有漂亮的注释

insertLink = (type, data, text) => {
    const editorState = this.state.editorState;
    const contentState = editorState.getCurrentContent();
    const selection = editorState.getSelection();
    const textWithSpace = text.concat(' ');
    // create new content with text
    const newContent = Modifier.insertText(
      contentState,
      selection,
      textWithSpace,
    );
    // create new link entity
    const newContentWithEntity = newContent.createEntity(
      type,
      'MUTABLE',
      data,
      false,
    );
    const entityKey = newContentWithEntity.getLastCreatedEntityKey();
    // create new selection with the inserted text
    const anchorOffset = selection.getAnchorOffset();
    const newSelection = new SelectionState({
      anchorKey: selection.getAnchorKey(),
      anchorOffset,
      focusKey: selection.getAnchorKey(),
      focusOffset: anchorOffset + text.length,
    });
    // and aply link entity to the inserted text
    const newContentWithLink = Modifier.applyEntity(
      newContentWithEntity,
      newSelection,
      entityKey,
    );
    // create new state with link text
    const withLinkText = EditorState.push(
      editorState,
      newContentWithLink,
      'insert-characters',
    );
    // now lets add cursor right after the inserted link
    const withProperCursor = EditorState.forceSelection(
      withLinkText,
      newContent.getSelectionAfter(),
    );
    // update the editor with all changes
    this.setState({editorState: withProperCursor });
  };