8

I'm using ngOptions to built a selection menu but one of my labels has an HTML entity in it &. The label shows up as Books & Stuff not Books & Stuff. My jade is this:

select(ng-show="isType === 'select'", id="{{id}}", ng-model="model", ng-options="o.id as o.label for o in options")

How can I get HTML entities to display properly?


Update

I'm trying the answer by sal:

select(ng-show="isType === 'select'", id="{{id}}", ng-model="model")
  option(ng-repeat="o in options", ng-bind-html="o.label", value="{{o.id}}")

An this displays the correct html entity but the correct option is not selected any more based on the model. See http://jsfiddle.net/ucLvjvkn/1/ for example.

scniro
  • 16,844
  • 8
  • 62
  • 106
Justin808
  • 20,859
  • 46
  • 160
  • 265

2 Answers2

10

A way you can solve this is to use ng-repeat along with ng-bind-html (included with ngSanitize) in place of ng-options. Here is a working example

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

<option ng-repeat="options in options" ng-bind-html="options.text" value="{{options.text}}"></option>

JSFiddle Link - working demo

Furthermore, if you must use ng-options use the following helper function to decode your values first before binding

function htmlDecode(input) {
    var e = document.createElement('div');
    e.innerHTML = input;
    return e.childNodes[0].nodeValue;
}

JSFiddle Link - ng-options demo

scniro
  • 16,844
  • 8
  • 62
  • 106
  • I tried this, but the correct option isn't selected based on the model. See http://jsfiddle.net/ucLvjvkn/1/ – Justin808 Feb 14 '15 at 17:54
  • @Justin808 I see you updated your question, but is there any reason my second fiddle will not work for you using `htmlDecode()`? – scniro Apr 19 '15 at 12:22
  • 2
    The htmlDecode does not work with markup, only html entities. I was hoping this technique would let me use ng-options and insert a flag icon in a country list select. – pduey Aug 12 '15 at 18:18
  • The second approach is genius! I had to add some nbsp's and this helped. Thanks. – tkit Sep 19 '18 at 14:22
7

Building on the other answers, you can do this with a filter, and gain the benefit of continuing to use ng-options. Example filter:

myApp.filter('decoded', function() {
  "use strict";

  function htmlDecode(input) {
    var e = document.createElement('div');
    e.innerHTML = input;
    return e.childNodes[0].nodeValue;
  }

  return function(input) {
    return htmlDecode(input);
  }
});

Then you can apply the filter in the ng-options. For example:

ng-options="o.id as o.label | decoded for o in options"

I was surprised that this worked, but it did for me in 1.3.20, and it is more elegant than other solutions!

It can be expensive to do this though. Optimized es6 version of the filter here: https://gist.github.com/DukeyToo/ba13dbca527f257a6c59

Steve Campbell
  • 3,385
  • 1
  • 31
  • 43