简体   繁体   中英

Draft.js adding hyperlink using applyEntity doesn't seem to work

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
    });

According to the official example you need to add a decorator to find the entities and apply the Link component

const decorator = new CompositeDecorator([
  {
    strategy: findLinkEntities,
    component: Link,
  },
]);

And as you're using the linkify plugin you have to pass the decorator to plugins editor

import Editor from "draft-js-plugins-editor";
import createLinkifyPlugin from "draft-js-linkify-plugin";
import "draft-js-linkify-plugin/lib/plugin.css";

...
<Editor
  decorators={[decorator]}
  editorState={editorState}
  onChange={setEditorState}
  plugins={[linkifyPlugin]}
/>
...

you can check out the working example here https://codesandbox.io/s/test-selection-decorator-draft-js-link-0lblg?file=/src/ExtendedEditor.js

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM