[SOLVED] Use HTML from item value

Hi all,
I have an item which contains an HTML string. I want to display this string on HABPanel and the contained html-tags should evaluated by the browser.

Example:
item contains value: “<b><i>example</i></b>

Result should be on HABPanel: example

I played with ng-bind-html and [innerHTML] but both did not work. The string was always printed including the html tags instead of the tags being evaluated.

Any ideas how to solve this?

Post your code

The actual piece of code is
<p style="margin-top: 12px;" [innerHTML]="{{itemValue(config.forecastPrecip1)}}"></p>
or
<p style="margin-top: 12px;" ng-bind-html="{{itemValue(config.forecastPrecip2)}}"></p>
and below is the context (whole custom widget). I build the html code of forecastPrecip1 in a NodeRED flow that queries Weatherunderground. I have several of those items for my dashboard which I need in other systems, too (eg NodeRED Dashboard) and therefore want to keep the html creation in NodeRED.

<div style="  
height: 100%;
overflow: hidden;
border-style: none;
 margin-left: 8px;"
 ng-init="ServerPath='/static/weather-underground-icons-master/dist/icons/white/png/128x128/'; IconSet='white'">
    <div style="width: 62%; height: 100%; text-align: left; font-size: 110%; float: left;">
        <div style="width: 49%; overflow: hidden; float: left; padding-right: 5px; height: 100%; ">
            <p style="width:100%; font-size: 110%; hyphens: auto;" lang="de">
                <img  src="{{ServerPath + itemValue(config.forecastIcon1)}}.png" style="width: 70px; height: 70px; float: right;">{{itemValue(config.forecastTitle1)}}: <font class="color-primary-2">{{itemValue(config.forecastNarrative1)}}</font>
            </p>
            <p style="margin-top: 12px;" [innerHTML]="{{itemValue(config.forecastPrecip1)}}"></p>
        </div>
        <div style="width: 48%; overflow: hidden; float: right; padding: 0px; padding-left: 5px; ">
            <p style="width:100%; font-size: 110%; hyphens: auto;" lang="de">
                <img src="{{ServerPath + itemValue(config.forecastIcon2)}}.png" style="width: 70px; height: 70px; float: right;">{{itemValue(config.forecastTitle2)}}: <font class="color-primary-2">{{itemValue(config.forecastNarrative2)}}</font>
            </p>
            <p  style="margin-top: 12px;" ng-bind-html="{{itemValue(config.forecastPrecip2)}}">
            </p>
        </div>
    </div>

I also tried to append .toString()to the itemValue(...) functions. But that did not make a difference.

It appears in the browser as
<p style="margin-top: 12px;" [innerhtml]="<img height=&quot;14px&quot; class=&quot;greyscale&quot; src=&quot;/static/drop.svg&quot;> 0 mm"></p>
and
<p style="margin-top: 12px;" ng-bind-html="<img height='14px' src='/static/drop.svg'> 1 mm"></p>

First, [innerHTML] is Angular 2+.

Second, ng-bind-html takes a literal string, or an object that resolves to a string.

p style="margin-top: 12px;" ng-bind-html="****<img height='14px' src='/static/drop.svg'> 1 mm"****></p>

I wrapped your value with ***. This is an invalid value. Just remove {{}} and you should be golden.

ng-bind-html="itemValue(config.forecastPrecip2)"

Or as string literal (note the apostrophe):

ng-bind-html="'{{itemValue(config.forecastPrecip2)}}'"
1 Like

Would someone please help:

when I use ng-bind-html it does not work as expected for SVG images.

The widget source is:

<div id="wrapper" ng-bind-html="itemValue('Weather_GIS_ConditionIcon')"></div>`

When item’s ‘Weather_GIS_ConditionIcon’ value is:

<b>test</b>

then I get the following HTML code rendered in browser (which is correct and as expected):

<div id="wrapper" ng-bind-html="itemValue('Weather_GIS_ConditionIcon')" class="ng-binding">
<b>test</b>
</div>`

But when the item value contains an SVG image source like this:

<div class="icon">
<svg height="41" viewbox="0 0 55 41" width="55" xmlns="http://www.w3.org/2000/svg"><path d="m47.0012324 23c0 2.8010266-1.1516228 5.3330774-3.0072158 7.1484995-.1160834-2.6811023-1.62491-5.1196885-3.9564501-6.3692776-.3179647-2.7606883-2.1665386-5.0416961-4.6348674-5.9438982l-.0786498-.6498596c-.4963276-4.1010087-3.8603579-7.25613643-7.868322-7.25613643-.6463494 0-1.2953414.08443413-1.933661.25019573-1.0040845-1.09139412-2.219879-1.93147294-3.5501994-2.47327607 1.7370338-2.2540443 4.4636096-3.70624733 7.5293655-3.70624733 5.1460278 0 9.336404 4.09163076 9.4953248 9.1990884 4.5668097.9247332 8.0046752 4.9613442 8.0046752 9.8009116zm-42 1.2703149c0-.0865884-.0027729-.1841381 0-.2703149.09843905-3.0593105 1.93602481-5.8288675 4.62869693-6.9631003l.82137627-.3472861.1720059-.9185616c.7392386-3.9239222 4.0054172-6.771052 7.762489-6.771052 2.1945241 0 4.3088433.97918249 5.8018155 2.6868439l.6735286.7706053.9537628-.2835828c.544041-.1623408 1.0958126-.2445387 1.6408199-.2445387 2.982552 0 5.5066611 2.3884244 5.8828103 5.4964344-.0945598-.0039094-.1895746-.0058827-.2850065-.0058827-.518816 0-1.039344.0600374-1.5528287.1780794-1.6247714-1.6545914-3.8395516-2.5979588-6.1428668-2.5979588-4.0599929 0-7.5727147 2.9008602-8.4878756 6.9188094-2.9380064 1.3468728-4.8687276 4.391037-4.8687276 7.6957986 0 .8272274.1225157 1.6273332.3499141 2.3834589-3.9653846-.0925368-7.3499141-3.495856-7.3499141-7.727752zm33.1308346.8075497.7379209.3513961c1.9030161.9073486 3.1312445 2.8901049 3.1312445 5.0528032 0 3.0675005-2.6757511 5.5179361-5.634814 5.5179361h-.365186-15.623101c-.1683546.0050374-.2939876.0050374-.376899 0-3.2623492-.1982073-6-2.9710374-6-6.385392 0-2.6108555 1.5783309-5.0120617 3.9273792-5.97543l.6969253-.2868885.1459444-.7588117c.6272328-3.241501 3.3985359-5.5934778 6.5863543-5.5934778 1.8620205 0 3.6559883.8088899 4.9227526 2.2195667l.5714788.636587.8092532-.234264c.4616106-.1341077.9297804-.2020103 1.3922109-.2020103 2.6212591 0 4.825183 2.116864 5.0186823 4.8185392z" fill="#ddd" fill-rule="evenodd"/></svg>
</div>

The SVG part of the code magically disaears when being rendered in browser:

<div id="wrapper" ng-bind-html="itemValue('Weather_GIS_ConditionIcon')" class="ng-binding">
<div class="icon>

      </div>
</div>`

Any ideas?..

Problem solved, according to this post

some HTML values are treated as unsafe by default so must be processed with $sce.trustAsHtml(html)

Good job tracking down the problem and thanks for posting your solution

I’ve got the same problem: Basicly works, but “unsafe” html is ignored.

<div ng-bind-html="itemValue('String_MyLog')">
</div>

How/where to insert the $sce.trustAsHtml(html) ?

Ok.
With help of: https://stackoverflow.com/a/19705096/9077523, Add angularjs code in template widget, https://www.w3schools.com/angular/angular_controllers.asp, Custom widget: Angular radial color picker I got the following:

HabPanel template widget with:

<div oc-lazy-load="['/static/myLog.js']">
  <div ng-bind-html="itemValue('String_MyLog') | unsafe">
  </div
</div>

openHAB-conf/html/myLog.js with:

var app = angular.module('app.mylog', [])

app.filter('unsafe', function($sce) {
    return $sce.trustAsHtml;
});