HTML in ternary statement


#1

Hi all, am I missing something here?

{{ 1 == 1 ? 'cat' : 'dog' }} {{ 1 == 1 ? '<b>Cat</b>' : 'dog' }}

The first one works as expected, the second one does not. Webstorm highlights the space after the ? in the second statement and has the error “expression expected”. I would assume the issue relates to HTML within a ternary return.

I know I could use <b ng-if="1==1">cat</b> but, I dunno, a ternary seems neater to me!

Cheers
-Chris


#2

Probably releated to where you’re embedding the ternary as opposed to the ternary itself. Can you show a bit more context?


#3

Cheers for the reply,

a simple app based on sidemenu, just putting the above code into the content area of a template reproduces my issue. The NON HTML one works fine, the HTML one does not.

Ta
-Chris


#4

Annoyingly difficult to get to the bottom of:

  1. If the expression didn’t generate an error during angular’s link / render, I don’t think it would have the effect you want anyway. I think the presence of an interpolated expression as the content of an element is equivalent to setting it in ng-bind. You want the content to be interpreted as html, so you’d use ng-bind-html. As it is, I think you’d see the literal string '<b>Cat</b>' as opposed to the word Cat

  2. There are two parsers at play; the html parser parsing tokens for the html in your page, before angular ever gets it’s hands on it, and the angular / js parser kicking in when the html parser has done it’s bit.

I think the embedded tags in the string constant are confusing the html parser so that the correct value isn’t being passed to the angular / js parser and it’s generating an error.

I’ve tried quite a few variations splitting and escaping strings etc. but no success.

(At this point, I’m not concerned about your question so much, but it’s clear there’s part of the process I don’t understand to my satisfaction :smile: )

I don’t see this, as I tend to wrap the majority of these things in small scope level functions or variables and use those instead.

So in your case, I’d have a bit of code on the scope that looked like:

$scope.dogOrCat = (1 == 1) ? 'dog' : '<b>Cat</b>' ;

and in my template I’d use:

<div ng-bind-html="dogOrCat"></div>

I tend to do that for even small fragments now as they tend to turn into larger fragments, and naming the variable bound to appropriately conveys the intention.

That said, still mulling over how you’d embed inline as you’re trying, and which step is causing the problem


#5

Gah, stupid cut and paste error in one of my earlier tests.

You can get the effect you want with:

<span ng-bind-html="1 == 1 ? '<b>dog</b>' : 'cat'"></span>

Just using ng-bind, or adding that expression to the element content won’t work.

Led myself astray with the schoolboy error of leaving the braces inside the bind statement:

<span ng-bind-html="{{1 == 1 ? '<b>dog</b>' : 'cat'}}"></span>

which is incorrect on general principles


#6

Cheers for the detailed responses :smile:

That makes sense to me, in the way it fails, you can see that the HTML is getting parsed before angular is doing anything so that’s messing it right up!

In the “full” version I’m basically appending some badges to an element based on whether a variable is true or false. It’s a cosmetic thing so I didn’t want to have to have anything additional in the $scope / controller.

<span ng-if="item.overdue" class="badge badge-assertive emfbadge">Overdue</span>

So basically, if item.overdue = true, show this badge. I’m not sure why I was so keen on using a ternary, the more I see the above, the more elegant it seems!

Regardless, thank you so much for your input!

-Chris