【问题标题】:How to programatically add mentions using draft-js-mention-plugin?如何使用 Draft-js-mention-plugin 以编程方式添加提及?
【发布时间】:2017-11-15 20:45:48
【问题描述】:

问题

我正在尝试为使用draft-js + draft-js-mention-plugin 创建的内容创建一个编辑界面。然而,editorState 没有被持久化,只有纯文本。提及被保存为对象数组。现在我需要使用该数据重新创建 editorState。


示例:

我有这样的纯文本:

const content = '@marcello we need to add spell check'

还有一个 mentions 数组,其中包含这样的对象:

const mentions = [{
  length: 8,
  offset: 0,
  user: 'user:59441f5c37b1e209c300547d',
}]

要使用纯文本创建 editorState,我使用这些行:

const contentState = ContentState.createFromText(content)
EditorState.createWithContent(contentState)

效果很好。纯文本设置为初始状态,但没有提及。

现在我需要一种方法来添加基于 mentions 对象的提及。

我正在尝试阅读库代码以找出答案,但到目前为止还没有成功。

【问题讨论】:

    标签: reactjs draftjs draft-js-plugins


    【解决方案1】:

    使用"draft-js": "^0.11.6""draft-js-mention-plugin": "^3.1.5" 你可以做到

    const stateWithEntity = editorState.getCurrentContent().createEntity(
      'mention',
      'IMMUTABLE',
      {
        mention: {id: 'foobar', name: 'foobar', link: 'https://www.facebook.com/foobar'},
      },
    )
    const entityKey = stateWithEntity.getLastCreatedEntityKey()
    const stateWithText = Modifier.insertText(stateWithEntity, editorState.getSelection(), 'foobar', null, entityKey)
    EditorState.push(editorState, stateWithText)
    

    https://github.com/draft-js-plugins/draft-js-plugins/issues/915#issuecomment-386579249https://github.com/draft-js-plugins/draft-js-plugins/issues/983#issuecomment-382150332 可能会对您有所帮助

    【讨论】:

    • 你是个传奇。
    【解决方案2】:

    我如何“破解”我的解决方案:

    // Imports
    import { EditorState,convertToRaw, ContentState, convertFromRaw, genKey, ContentBlock  } from 'draft-js';
    // Init some kind of block with a mention
    let exampleState = {
      blocks: [
            {
              key: genKey(), //Use the genKey function from draft
              text: 'Some text with mention',
              type: 'unstyled',
              inlineStyleRanges: [],
              data: {},
              depth: 0,
              entityRanges: [
                { offset: 15, length: 7, key: 0 }
              ]
            }
      ],
      entityMap: [
        "0": {
          "type": "mention",
          "mutability": "SEGMENTED",
          "data": {
            "mention": {
              "name": "<name>",
              "link": "<link>",
              "avatar": "<avatar-url>"
            }
          }
        }
      ]
    };
    this.state.editorState = EditorState.createWithContent(convertFromRaw(exampleState));
    

    在这里,您可以创建一些函数来输入您的文本并输出 entityRange,返回提及的偏移量/长度,并用突出显示的内容替换“entityRanges”数组!

    在本例中,“提及”一词会以您在提及插件中使用的任何样式突出显示

    旁注:

    您可以使用草稿中的 ContentBlock 类或创建自己的实现以使其更漂亮

    【讨论】:

      【解决方案3】:

      这是我设法提出的添加提及 (#) 的解决方案(使用 entityMap,到状态结束时的新块)。它可以作为提及等被检索...... 当然,这可以简化,但对我来说可以正常工作。

       // import {....} from 'draft-js';
       import Immutable, {List, Repeat} from 'immutable' ;
      
        const addMentionLast = (editorState, mentionData) => {
         
          if(!mentionData.id) return;
      
          // debugger;
          const contentState = editorState.getCurrentContent();
          const oldBlockMap = contentState.getBlockMap();
          const lastKey = lastNonEmptyKey(contentState);
          const charData = CharacterMetadata.create();
          
          //new state with mention
          const selection = editorState.getSelection();
          const entityKey = Entity.create('#mention', 'SEGMENTED', {"mention":{...mentionData }} );
          //add text 
          const textWithEntity = Modifier.insertText(contentState, selection , `#${mentionData.name}` , null,  entityKey); 
          const _editorState = EditorState.push(editorState,  textWithEntity ,  'insert-characters');
          
          //create new block
          const _newBlock = new ContentBlock({
            key:  genKey(),
            type: 'unstyled',
            depth: 0,
            text: mentionData.name,
            characterList: List(Repeat(charData, mentionData.name.length)),
          });
      
          //set the entity
          const __newBlock =  applyEntityToContentBlock(_newBlock,0, mentionData.name.length, entityKey)
      
          //set new block in order..
          const blocksMap =
            Immutable.OrderedMap().withMutations(map => {
              if (lastKey) {
                //after the last non empty:
                for (let [k, v] of oldBlockMap.entries()) {
                  map.set(k, v);
                  if (lastKey === k) {
                    map.set(k, v);
                    map.set(__newBlock.key, __newBlock);
                  }
                }
              }
              else {
                // first line:
                map.set(__newBlock.key, __newBlock);
              }
            });
         
          return EditorState.push(
            _editorState,
                ContentState
                  .createFromBlockArray(Array.from(blocksMap.values()))
                  .set('selectionBefore', contentState.getSelectionBefore())
                  .set('selectionAfter', contentState.getSelectionAfter())
          )
      
        }
      
        function lastNonEmptyKey (content){
          const lastNonEmpty = content.getBlockMap().reverse().skipUntil((block, _) => block.getLength()).first();
       if (lastNonEmpty) return lastNonEmpty.getKey();
      }
      

      感谢大家的分享!

      【讨论】:

        猜你喜欢
        • 2018-08-10
        • 1970-01-01
        • 2017-10-07
        • 1970-01-01
        • 2021-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-15
        相关资源
        最近更新 更多