Saturday, 27 July 2019

How to display children components in an Anchor tag in DraftJS?

We're using DraftJS to insert an <a> around some selected text in an editor.

Current state

It presently works by wrapping the anchor tag around the highlighted text.

E.g., for this text: Foo bar foo.
If the user highlights "bar", our editor will render <a href='http://...'>bar</a>

The current code to alter the content state:

private addLinkToSelection(url: RawDraftContentStateWithSelection, color?: string, underline?: boolean) {
  const {editorState} = this.props;
  const selectionState = editorState.getSelection();

  let entity = null;
  if (url) {
    entity = Entity.create('LINK', 'MUTABLE', {url, color, underline});
  }

  const update = RichUtils.toggleLink(editorState, selectionState, entity);

  this.props.onChange(update);
}

And the actual Link that is getting rendered:

const Link = (props, style = null) => {
  const {url} = props.contentState.getEntity(props.entityKey).getData();
  return (
    <a href={url} style={style}>
      {props.children}
    </a>
  );
};

Desired state

Our product owner has asked that the links retain any other elements which may be selected.

E.g., for text with an image: Foo bar <img src='http:\...'/> foo.

If the user highlights "bar" and the image, we want to render the anchor tag around both of them. I.e. <a href='http://...'>bar <img src='http:\...'/> </a>.

However, our code is stripping anything that isn't text-- the <img> disappears.

Any help is greatly appreciated.

Update

If this helps any, here's the custom decorator which creates the Link:

private decorate(editorState: EditorState) {
  if (editorState.getDecorator()) {
    return editorState;
  }

  const decorator = new CompositeDecorator([{
    strategy: findLinkEntitiesFactory(editorState),
    component: (props) => {
      const data = props.contentState.getEntity(props.entityKey).getData() as LinkData;
      return Link(props, {
          color: (data.color == null ? this.props.linkColor : data.color) || undefined,
          textDecoration: (data.underline == null ? this.props.linkUnderline : data.underline) ? 'underline' : 'none'
        }
      );
    }
  }]);
  return EditorState.set(editorState, {decorator});
}

function findLinkEntitiesFactory(state: EditorState) {
  return (contentBlock: ContentBlock, callback) => {
    contentBlock.findEntityRanges(
      linkEntityFilterFactory(state),
      callback
    );
  };
}



from How to display children components in an Anchor tag in DraftJS?

No comments:

Post a Comment