1

I want to replace certain letters (A,B,C,...) of a larger text with span tags which i css into nice symbols. Since I later reuse these tags I created an angular template directive symbol:

.directive('symbol', function() { return {
    restrict: 'E',
    replace: true,
    template: '<span class="{{f1(kind)}}">{{f2(kind)}}</span>',
    scope: { kind: '=' }
}})

I can replace the letters with spans using a filter and regular expressions:

.filter('symbolify', ['$sce', function($sce) {
    return function(text) {
        text = text.replace(/[ABCD]/g, '<symbol kind="\'$&\'"></symbol>');
        // this is the smallest example that reproduced the issue
        return $sce.trustAsHtml(text);
    }
}])

And insert it into the DOM with bind-html-compile:

<div bind-html-compile="text | symbolify"></div>

This does not work for me and I get $rootScope:infdig errors.

Also, doing it this way, I can later not use ng-repeat with a list of letters since I overwrite the scope in the directive:

<symbol ng-repeat="kind in ['A', 'B', 'C', 'D']"></symbol>

Does not work. (Solved: move repeat to enclosing div and add kind="kind")

Here (updated) is a jsFiddle with the issue I described here (Opening the console might take some time).

Here (2. update) is a not so nice way of doing it, but it works.

Is there an official way of doing this that works for both cases? Or can I not use templates for this?

Community
  • 1
  • 1
  • Generally an infinite digest error means if angular executes it twice it doesn't get the same result both times. Probably it's repeatedly doing the find-and-replace on itself. – Casey Jul 20 '16 at 23:28
  • Are one-way bindings possible in angular? The user will never update the symbolified text but only the raw version. – Fabian Meier Jul 21 '16 at 08:27

2 Answers2

0

there are no f1 and f2 functions in your directive scope

another thing is that you want to access your controller outside your ng-controller

simplified version fiddle

angular.module('foo', [])
.controller('bar',function($scope){
$scope.kinds=['A','B','C'];
})
  // the directive with template
  .directive('symbol', function() {
    return {
      restrict: 'E',
      replace: true,
      template: '<span class="{{f1(kind)}}">{{f2(kind)}}</span>',
      scope: {
        kind: '='
      },
      link:function(scope,elem,attrs){
        scope.f1=function(kind){
            return kind.replace(/[A-Z]+/,"$&-testing testing");
        }
        scope.f2=function(kind){
            return kind.replace(/[A-Z]+/,"$&-testing testing");
        }
      }
    };
  })


    // provider of text with symbols A, B, C, D
  .controller('bar', ['$scope', function($scope) {
    $scope.text = "Lorem ipsum dolor sit amet, A consectetur adipiscing elit. Nullam pretium B tellus a nisl blandit tristique. Vestibulum laoreet D pulvinar ante ac finibus. Fusce nisi mauris, pharetra B imperdiet dui eget, C rutrum tincidunt libero. Quisque pharetra nisl dictum, egestas sem sed, malesuada ex. D Suspendisse placerat faucibus tempor. donec pulvinar risus nunc, id venenatis tortor A sodales ac."
  }])

html:

<div ng-app="foo">
  <h1>Text</h1>
  <div ng-controller="bar">
    <div>{{text}}</div>
    <h3>Legend</h3>
    <div ng-repeat="kind in ['A','B','C']">
    <symbol kind="kind"></symbol>
    </div>
  </div>
</div>
neuronet
  • 1,139
  • 8
  • 19
  • Thanks! This fixed the issue with the legend part, but not the issue with the replacement. I updated my [Fiddle](https://jsfiddle.net/awmuLLns/7/) and removed the functions f1, f2 which are not relevant for the solution I'm looking for (Sorry for the confusion). – Fabian Meier Jul 21 '16 at 08:17
0

I have found a way of doing it: instead of applying the filter in the bind-html-compile statement, it can be applied in the controller. This will not cause an infinite update loop.

jsFiddle

$scope.text2 = symbolifyFilter($scope.text);

and then

<div bind-html-compile="text2"></div>

It's not a nice solution but it works.