0

How do you evaluate ng-attr for elements that have been inserted with ng-bind-html? JS Fiddle illustrating what I'm talking about here.

HTML:

<body ng-app="TestApp" ng-controller="TestCtrl">
    <div ng-bind-html='y | to_trusted'></div>
    <svg width="100" height="100">
        <path ng-attr-d="M{{x}},10L50,50L10,50Z" />
    </svg>
</body>

Javascript:

var app = angular.module("TestApp", []);

app.controller('TestCtrl', function ($scope, $interval) {
    $scope.y = '<svg width="100" height="100"><path ng-attr-d="M{{x}},10L50,50L10,50Z"/></svg>';
    $scope.x = 10;
});

app.filter('to_trusted', ['$sce', function ($sce) {
    return function (text) {
        return $sce.trustAsHtml(text);
    };
}]);

The ng-attr-d in the second <path> is evaluated, but the first is not.

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
Puzzler3141
  • 1,682
  • 2
  • 14
  • 21
  • 1
    HTML must be compiled before Angular can perform any data binding. You may need to write a directive that watches the HTML value of an associated model on your element and uses the $compile service to make it Angular-friendly. – cmw Apr 18 '14 at 20:54
  • @cmw I'm new to Angular, could you provide an example of how to do this? Also, if it were to be done this way, could you update the inserted SVG to create animations? – Puzzler3141 Apr 18 '14 at 21:37

1 Answers1

2

Here's how this might look as a directive...

  • restrict: 'E': This directive is used as an element
  • x: '=': property on the isolated scope passed in as an attribute
  • template is the template

.

app.directive('myPath', function () {
    return {
        restrict: 'E',
        scope: {
            x: '='
        },
        template: '<svg width="100" height="100"><path ng-attr-d="M{{x}},10L50,50L10,50Z"/></svg>'
    };
});

And it can be used like this...

<my-path x="x"></my-path>

JsFiddle

Anthony Chu
  • 37,170
  • 10
  • 81
  • 71
  • Thanks! I had just started looking at directives as @cmw suggested. There's quite a lot to AngularJS. – Puzzler3141 Apr 18 '14 at 22:37
  • This answer's good, and is the way you should look into doing it @Puzzler3141. Using a directive with a scope isolate and a template will get you two-way databinding for free. Note: `restrict: 'E'` will cause problems in older versions of Internet Explorer. To keep your code legacy browser friendly, use `restrict: 'A'` in your directive initialization object. Then in your html use as `
    `.
    – cmw Apr 19 '14 at 01:16