I've been working on this problem for a while, and I hope it's not a bug.
I'm testing a text editor using Draft.js, and I'd simply like my users to add a hyperlink to their articles, so I create a function for that to happen by modifying the editor state's content.
const addLlink = (e) => {
e.preventDefault();
const contentState = editorState.getCurrentContent();
const contentStateWithEntity = contentState.createEntity(
'LINK', 'MUTABLE', {url: 'https://www.amazon.com'} // link for testing only
);
const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
const contentStateWithLink = Modifier.applyEntity(
contentStateWithEntity,
editorState.getSelection(),
entityKey
);
// tried with and without styling
const styledContentStateWithLink = Modifier.applyInlineStyle(
contentStateWithLink,
editorState.getSelection(),
'HYPERLINK'
);
const newState = EditorState.set(editorState, {
currentContent: styledContentStateWithLink
});
setEditorState(newState);
// Also tried: setEditorState(RichUtils.toggleLink(newState, newState.getSelection(), entityKey));
}
When I trigger it, I just use an Evergreen-ui button:
<Button onMouseDown={addLlink} appearance="minimal">Link</Button>
The styling I implement using the Modifier object works, but I can't seem to get the link to actually work. It should be noted that the link plugin as a package, which works great, but that's only for detecting typed out/pasted URLs (not embedded into text).
Does anyone have an actual working example, or suggestions of what I may be doing wrong, for links that use React functional programming?
It turns out that I needed to add a Decorator in order for the entity to be detected. I placed this code above/outside of my Editor component:
const findLinkEntities = (contentBlock, callback, contentState) => {
contentBlock.findEntityRanges(
(character) => {
const entityKey = character.getEntity();
return (
entityKey !== null &&
contentState.getEntity(entityKey).getType() === 'LINK'
);
},
callback
);
}
const Link = (props) => {
const {url} = props.contentState.getEntity(props.entityKey).getData();
return (
<a href={url} >
{props.children}
</a>
);
};
const strategyDecorator = new CompositeDecorator([
{
strategy: findLinkEntities,
component: Link,
},
]);
Basically, it detects link entities and converts them into elements when you set the new content using EditorState:
const newState = EditorState.set(editorState, {
currentContent: styledContentStateWithLink,
decorator: strategyDecorator
});