Adding a data attribute to a hyperlink

Hey all,

I have an issue with formatting a link in my application. I am using the method documentToHtmlString and I pass in the options like this:

{
      renderNode: {
        [INLINES.HYPERLINK]: (node, next) => {
          console.log(node);

          let value = node.content[0]['value'];
          let uri = node.data.uri;

          return `<a class="test" href="${uri}" data="test" category="contact" data-category="contact" data-action="email" target="_blank">${value}</a>`;
        },
      },
    }

The problem I have is that the renderer ignores most of the attributes. Infact, the only ones it uses is class, href and target. All others are ignored. Does anyone know why?

Hi @jaymie.jeffrey, I think it’s possible that React might consider the additional non-standard attributes as dangerous, therefore stripping them from the output. You might want to look at this thread: https://stackoverflow.com/questions/54083103/contentful-documenttohtmlstring-doesnt-include-embedded-image-in-rich-text

A possible solution would be the last one about using dangerouslySetInnerHTML to print the <a> tag with your custom attributes.

I was actually using Angular, so if I got my method to return SafeHtml then I was able to bind to innerHtml and all the tags where created find.
This is the basic function I created:

public htmlToString(text: any): SafeHtml {
  const renderOptions = {
    renderNode: {
      [BLOCKS.EMBEDDED_ASSET]: (node) =>
        `<img class="img-fluid mb-4" src="${node.data.target.fields.file.url}"/>`,
      [BLOCKS.HEADING_1]: (node) => this.parseContent(node),
      [BLOCKS.HEADING_2]: (node) => this.parseContent(node),
      [BLOCKS.HEADING_3]: (node) => this.parseContent(node),
      [BLOCKS.HEADING_4]: (node) => this.parseContent(node),
      [BLOCKS.HEADING_5]: (node) => this.parseContent(node),
      [BLOCKS.HEADING_6]: (node) => this.parseContent(node),
      [BLOCKS.PARAGRAPH]: (node) => this.parseContent(node),
      [BLOCKS.UL_LIST]: (node) => this.parseList(node),
      [BLOCKS.OL_LIST]: (node) => this.parseList(node),
      [INLINES.HYPERLINK]: (node) => `<p>${this.formatHyperLink(node)}</p>`,
    },
  };

  const content = documentToHtmlString(text, renderOptions);

  return this.sanitizer.bypassSecurityTrustHtml(content);
}

And the method for formatting the hypelink looks like this:

private formatHyperLink(content: any) {
  const email = this.hrefService.isEmail(content.data.uri);
  let text = content.content.find(
    (content: any) => content.nodeType === 'text'
  );

  if (email) {
    return `<a href="${content.data.uri}" data-category="contact" data-action="email">${text.value}</a>`;
  }

  const outbound = this.hrefService.isExternal(content.data.uri);

  if (outbound) {
    return `<a href="${content.data.uri}" data-category="navigate" data-action="outbound link">${text.value}</a>`;
  } else {
    return `<a routerLink="${content.data.uri}" data-category="navigate" data-action="inbound link">${text.value}</a>`;
  }
}