2

Hi I'm currently using a REST service to pull in data and using angular to print the data in the front end.

The issue I have is that the string that's being pulled through has escaped entities like ' instead of ' (apostrophe) eg. "has been inspired by France's most popular neighbourhood".
decodeURI doesn't seem to work at all.
I've found a workaround by creating custom filter which makes creates a dummy element, sets the innerHTML to the dummy element, then taking it's innerHTML once it's been parsed and returning that value.

.filter("decoder", function() {
  return function(item) {
    var txt = item;
    var dummy = document.createElement('p');
    dummy.innerHTML = txt;
    txt = dummy.innerHTML;
    dummy.remove();
    return txt;
  }
})

It feels really dirty so I was wondering if their was a way to avoid DOM manipulation for this.
Thanks!

4
  • 2
    What does the JSON actually look like? When you say "escaped", do you mean escaped with HTML syntax like ' or whatever? Commented May 8, 2015 at 2:22
  • Sorry it looks like SO decoded it when i put it in. I've updatted correctly now Commented May 8, 2015 at 2:23
  • 4
    If possible, fix the service to return the actual information :< Using HTML/character encoding outside of the appropriate context is wrong. Commented May 8, 2015 at 2:26
  • 1
    Unfortunately I don't have access to the service :(, I'm kind of stuck doing it at the front end for now. Commented May 8, 2015 at 2:40

2 Answers 2

3

You could manually replace each of them.

.filter("decoder", function () {
  return function (item) {
    return item
      .replace(/&#039;/g, "'")
      .replace(/&quot;/g, '"')
      .replace(/&amp;/g, "&")
      .replace(/&lt;/g, "<")
      .replace(/&gt;/g, ">");
  }
})

I think this list covers all of them, but you can always add to it if you see anything else. It's still a bit messy, but I think it's better than adding an element to the DOM.

UPDATE

If you're looking for a more complete solution, you can do the following:

.filter("decoder", function () {
  return function (item) {
    // it would be better to define this globally as opposed to within the function
    var ENTITIES = {
      '&amp': '&',
      '&amp;': '&',
      '&apos': '\'',
      '&apos;': '\'',
      '&gt': '>',
      '&gt;': '>',
      '&lt': '<',
      '&lt;': '<',
      '&quot': '"',
      '&quot;': '"'
    };
    return item.replace(/&#?[0-9a-zA-Z]+;?/g, function (entity) {
      if (entity.charAt(1) === '#') { // if it's a numeric entity
        var code;

        if (entity.charAt(2).toLowerCase() === 'x') { // if it's a hex code
          code = parseInt(entity.substr(3), 16);
        } else {
          code = parseInt(entity.substr(2));
        }

        if (isNaN(code) || code < -32768 || code > 65535) { // if it's not a valid numeric entity
          return '';
        }
        return String.fromCharCode(code);
      }
      return ENTITIES[entity] || entity;
    });
  }
});

As you can see, this solution is significantly more complex, but it does cover the normal entities as well as the all of the numeric ones. If your goal is to avoid updating in the future, this is your best bet.

Sign up to request clarification or add additional context in comments.

1 Comment

This would work and I have considered this option. Unfortunately there may be times in the future where new entitities are entered into the content which would involve adding and updating, which I'm trying to avoid. I appreciate your effort though Robin.
0

You can use ng-bind-html instead of use filter to decode it. I think this can help you automatically decode entities in your html string.

2 Comments

I do not have access to add the ngSanitize module unfortunately
No, you dont need to add ngSanitize module. Just simple use ng-bind-html.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.