Skip to content

Instantly share code, notes, and snippets.

@nicubarbaros
Created April 17, 2018 21:13
Show Gist options
  • Save nicubarbaros/8a35a16dd45065891803bbfa3e451d15 to your computer and use it in GitHub Desktop.
Save nicubarbaros/8a35a16dd45065891803bbfa3e451d15 to your computer and use it in GitHub Desktop.
Draft Js Mentions
import { convertFromRaw, convertToRaw, ContentState } from 'draft-js';
const getIndicesOf = (searchStr, str, caseSensitive) => {
let tempStr = str;
let tempSearchStr = searchStr;
const searchStrLen = tempSearchStr.length;
if (searchStrLen === 0) {
return [];
}
let startIndex = 0;
let index;
const indices = [];
if (!caseSensitive) {
tempStr = tempStr.toLowerCase();
tempSearchStr = tempSearchStr.toLowerCase();
}
while ((index = tempStr.indexOf(tempSearchStr, startIndex)) > -1) {
indices.push(index);
startIndex = index + searchStrLen;
}
return indices;
};
const getEntityRanges = (text, mentionName, mentionKey) => {
const indices = getIndicesOf(mentionName, text);
if (indices.length > 0) {
return indices.map(offset => ({
key: mentionKey,
length: mentionName.length,
offset
}));
}
return null;
};
const createMentionEntities = (text, tags) => {
const rawContent = convertToRaw(ContentState.createFromText(text));
const rawState = tags.map(tag => ({
type: 'mention',
mutability: 'IMMUTABLE',
data: { id: tag.id, name: tag.name }
}));
rawContent.entityMap = [...rawState];
rawContent.blocks = rawContent.blocks.map(block => {
const ranges = [];
tags.forEach((tag, index) => {
const entityRanges = getEntityRanges(block.text, tag.name, index);
if (entityRanges) {
ranges.push(...entityRanges);
}
});
return { ...block, entityRanges: ranges };
});
return convertFromRaw(rawContent);
};
export default createMentionEntities;
@ramisalem
Copy link

Hey there, Do you have any resources on how to create a custom entity I am really confused I could not understand the concept from the draft docs

@andrew65215584
Copy link

This part of code works for me. But i have received an error that mention is undefined. to fix this i had to update code with
data: { mention : { id: tag.id, name: tag.name }}

also if some one need to create an editor state after using createMentionEntities. You should call EditorState.createWithContent(createMentionEntities(data))

@hanihusam
Copy link

Hi.

Is there a TypeScript version of this? I've tried to make it but always got error on

rawContent.entityMap = [...rawState];

it says,

Type '{ type: string; mutability: string; data: { mention: MentionState; }; }[]' is not assignable to type '{ [key: string]: RawDraftEntity<{ [key: string]: any; }>; }'.
  Index signature for type 'string' is missing in type '{ type: string; mutability: string; data: { mention: MentionState; }; }[]'

@treago
Copy link

treago commented Feb 19, 2023

@hanihusam there is how i managed to do this

  const rawState =
    mentions?.reduce<Record<string, RawDraftEntity>>(
      (previousValue, currentValue, index) => ({
        ...previousValue,
        [index.toString()]: {
          type: 'mention',
          mutability: 'MUTABLE',
          data: { mention: currentValue }
        }
      }),
      {}
    ) ?? {}
  rawContent.entityMap = rawState

@nicubarbaros
Copy link
Author

I've used a @ts-ignore ignore for that line, but probably @treago 's solution is better!

@hanihusam
Copy link

hanihusam commented Feb 21, 2023

@hanihusam there is how i managed to do this

  const rawState =
    mentions?.reduce<Record<string, RawDraftEntity>>(
      (previousValue, currentValue, index) => ({
        ...previousValue,
        [index.toString()]: {
          type: 'mention',
          mutability: 'MUTABLE',
          data: { mention: currentValue }
        }
      }),
      {}
    ) ?? {}
  rawContent.entityMap = rawState

Thanks! It helps me very much. @treago

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment