oink
oink

Reputation: 1493

Pre-processing AngularJS output

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.

Upvotes: 4

Views: 506

Answers (1)

Kristj&#225;n
Kristj&#225;n

Reputation: 18803

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>

Upvotes: 2

Related Questions