4

I want to add a pre-processing step to AngularJS before it updates any HTML. For the sake of simplicity, let's have it bold all instances of hello.

That is, if we let $scope.text = "hello world!", we want somehow to have

{{ text }}

evaluate during the $digest cycle into

<b>hello</b> world!

If $scope.text is changed, this would of course update as appropriate.

How would this be done? Preferably, it would be a directive, so that any expressions inside a <div boldhello></div> would be processed.

1
  • 3
    This case seems simple enough that a filter would probably work fine. Commented Dec 26, 2015 at 22:14

1 Answer 1

2

datasage's comment is spot on - this is a great place for a filter. Here's a basic filter adapted from the documentation examples that replaces any instance of hello with one surrounded by bold tags:

(function(angular) {
  'use strict';
  angular.module('myFilterApp', [])
    .filter('boldHello', function($sce) {
      return function(input) {
        input = input || '';
        var out = input.replace(/hello/gi, function(text) {
          return '<b>' + text + '</b>';
        });
        return out;
      };
    })
    .controller('MyController', ['$scope', function($scope) {
      $scope.greeting = 'Oh, hello, my friend.';
    }]);
})(window.angular);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="myFilterApp">
  <div ng-controller="MyController">
    <input ng-model="greeting" type="text"><br>
    No filter: {{greeting}}<br>
    Bold: {{greeting | boldHello}}<br>
  </div>
</body>

But alas, the tags are printed in the output! That's because Angular keeps you safe from accidental HTML injection (which might contain script tags), so we need to mark this explicitly safe. You mark it safe with trustAsHtml, and we need to put the result into your template using the ng-bind-html directive.

(function(angular) {
  'use strict';
  angular.module('myFilterApp', [])
    .filter('boldHello', function($sce) {
      return function(input) {
        input = input || '';
        var out = input.replace(/hello/gi, function(text) {
          return '<b>' + text + '</b>';
        });
        return $sce.trustAsHtml(out);
      };
    })
    .controller('MyController', ['$scope', function($scope) {
      $scope.greeting = 'Oh, hello, my friend.';
    }]);
})(window.angular);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="myFilterApp">
  <div ng-controller="MyController">
    <input ng-model="greeting" type="text"><br>
    No filter: {{greeting}}<br>
    Bold: <span ng-bind-html="greeting | boldHello"></span><br>
  </div>
</body>

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

2 Comments

Huh, filters are pretty cool. One thing - this is for a chat application, so if the user enters arbitrary HTML and this find-replace algorithm does its work, it ends up not sanitizing the HTML. How do you prevent this?
The simplest thing is to immediately remove any <tags> from the user's input, or convert </> to &lt;/&gt;. If you want them able to type some tags, you'll need a smarter filter, or some other solution.

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.