How to render strings as HTML within templates?

Is there a way to do something like:

<template>
    ...
        <div class="title">${getHtmlTitle()}</div>
    ...
</template>
...
<script>
  export default function (props, {...}) {
    
    let name = "Max";
    
    const getHtmlTitle = () => {  
      return `<span>Hello <strong>${name}</strong></span>`;
    }
    ...
  ...  
</script>    

in this case the getHtmlTitle() within the template returns/inserts the raw string but Dom doesn’t interpret it as HTML. It was quite easy with Template7 - but what is the right approach with pure JS template literal strings?

Will be available in next update with special innerHTML prop like so:

<div class="title" innerHTML=${getHtmlTitle()}></div>
1 Like
1 Like

Wow your are awesome! This makes particular things much easier. But if you have a scenario where you have like a typical list component with individual dynamic list item templates… would you still register individual components with registerComponent like:

Framework7.registerComponent(
  'item-product',
  (props, { $h }) => {
    return () => $h`
      <li class="item-content">Im a Product! ${props.item.title}</li>
    `
  }
)

...

<template>
    ${myList.map((item, index) => $h`
        <${myIndListItemCompId} index="${index}" item="${item}"></${myIndListItemCompId}>
        ...
    `)} 
</template>

<script>
    ...
    let myIndListItemCompId = 'item-product';
    ...
</script>

or now with the innerHtml feature like:

<template>
    ${myList.map((item, index) => $h`
        <li innerHTML=${renderItem(item)}></li>
        ...
    `)} 
</template>

<script>
    ...
    const renderItem = (item) => {  
      return `<li class="item-content">Im a Product! ${item.title}</li>`;
    }
    ...
</script>

The innerHtml approach would be more flexible as you can simply render it on demand without the need of register it on startup already… What would you recommend? Also in terms of performance?

You don’t have to register global components, you can use local components like here https://framework7.io/docs/router-component.html#local-components

If you have control over HTML I would never use innerHTML, only for “external” content. Also in your original example, it should work by just like this:

<template>
    ...
        <div class="title">${getHtmlTitle()}</div>
    ...
</template>
...
<script>
  export default function (props, { $h }) {
    
    let name = "Max";
    
    const getHtmlTitle = () => {  
      return $h`<span>Hello <strong>${name}</strong></span>`;
    }
    ...
  ...  
</script> 
1 Like

wow… didn’t know it’s that simple. Great!

I have a similar problem. I’m using the tree component and I want to add a node icon to each node based on the node type. The FW7 icons are in an array and I pull the html from the table and insert in the tree node.

for example, the tree block treeview-item-content would look like this:

 // <i class="f7-icons treeview-item-icon">person_crop_circle_fill_badge_checkmark</i>
const __icon = symbols[child.type]; // would contain the above icon html

$h `<div class="treeview-item-content">
     <span innerHTML=${__icon}></span>
     ${__itemContent}
 </div>`

But nothing is rendered. If I remove the span, I get the html text rendering in my tree node. What am I doing wrong?

Nevermind. My bad. I was linking to an older version of Fw7 so the innerHTML wasn’t being recognized.