Rich text with Send mail component

Hello,
I have a rich text component that I’m saving in an app variable,
I want to use that variable in a “Send Email” action component as (Message), but it’s not possible to do so nether in the message(text) or message(HTML), I simply can not select the app variable when I try to data bind it, I assume it’s because the type of the app variable is rich text, and the message fields accept strings or HTML
Does anyone know of any workaround for this, any suggestions are welcome, thank you

Hi!

We have a challenge registered on improvements to getting the String or HTML value from RichText.

But until then, I can provide you with the following workaround:

  1. Add App Variables (the data source) as a Function parameter
  2. Use the following code to return the HTML (in this example, the App Variable is named “richText”)

Disclaimer: The code below is an “undocumented hack”, and is not guaranteed to work for future versions of the RichText editor!

if(!appVariables.richText){
    return
}
const html = appVariables.richText.value.reduce((html, node) => {
    return html + " " + rtfToHtml(node);
}, "");
  function rtfToHtml(node) {
    if (node.bold || node.italic || node.underline || node.code) {
      let string = `${node.text}`
      if (node.bold) {
        string = `<strong>${string}</strong>`
      }
      if (node.italic) {
        string = `<em>${string}</em>`
      }
      if (node.underline) {
        string = `<span style="text-decoration: underline;">${string}</span>`
      }
      if (node.code) {
        string = `<code>${string}</code>`
      }
      return string
    }
      switch (node.type) {
          case 'block-quote':
            return `<blockquote><p>${rtfToHtml(node.children[0])}</p></blockquote>`
          case 'paragraph':
            return `<p>${node.children.map( childNode => rtfToHtml(childNode)).join("")}</p>`
          case 'link':
            return `<a href="www.google.com">${node.children.map( childNode => rtfToHtml(childNode)).join("")}</a>`
          case 'heading-one':
            return `<h1>${node.children.map( childNode => rtfToHtml(childNode)).join("")}</h1>\n`
          case 'heading-two':
            return `<h2>${node.children.map( childNode => rtfToHtml(childNode)).join("")}</h2>\n`
          case 'heading-three':
            return `<h3>${node.children.map( childNode => rtfToHtml(childNode)).join("")}</h3>\n`
          case 'heading-four':
            return `<h4>${node.children.map( childNode => rtfToHtml(childNode)).join("")}</h4>\n`
          case 'heading-five':
            return `<h5>${node.children.map( childNode => rtfToHtml(childNode)).join("")}</h5>\n`
          case 'heading-six':
            return `<h6>${node.children.map( childNode => rtfToHtml(childNode)).join("")}</h6>\n`
          case 'bulleted-list':
            return `<ul>${node.children.map( childNode => rtfToHtml(childNode)).join("")}</ul>`
          case 'numbered-list':
             return `<ol>${node.children.map( childNode => rtfToHtml(childNode)).join("")}</ol>`
          case 'list-item':
            return `<li>${node.children.map( childNode => rtfToHtml(childNode)).join("")}</li>`
          default:
            return node.text
      }
  }
return html
1 Like

Thank you so much for the code @kristian, It did help a lot.
We however are still facing a problem with this rich text, specifically with the link component
I tried to catch the URL from the rich text like this:

case 'link':
            const url = node.href
            return `<a href="${url}">${node.children.map(childNode => rtfToHtml(childNode)).join('')}</a>`;

This however did not work, not sure how else I would reach the URL stored in the rich text.

Hello,

The URL on a child node has the key of url.

If you need all the URLs in a richText then I wrote this Javascript that recursively goes over each node and extracts the URLs. The URLs are then collected in a list for you to work with.

Please note these kind of operations on richtext are not supported and might break at a later time. Appfarm does not provide any guarantee that this will continue to work in future releases.

const richText = appVariables.richText.value;
console.log("Rich Text", richText);

const extractUrls = (node) => {
    let urls = [];

    // If the passed nodes has children
    if (node.children) {
        for (let child of node.children) {
            urls = urls.concat(extractUrls(child));
        }
    }

    // If the passed node has a link prop itself
    if (node.type === "link") {
        urls.push(node.url);
    }

    return urls;
}

const allUrls = richText.flatMap(node => extractUrls(node));
console.table("allUrls", allUrls);

// Do whatever you need with the URLs here

resolve();

If provided with the richText:

PDF
A Link
elg
B link
Appfarm
C Link

The output will be:
AllUrls:

0: "https://ww1.microchip.com/downloads/en/devicedoc/50002687a.pdf"
1: "http://www.elg.no"
2: "https://www.appfarm.io/"

Does this work for your usecase?

// Erik

2 Likes

Hello,
That woks perfectly for my usecase, thank you so much for your help :slight_smile:

4 Likes