Jquery breaks angular directive

I'm relatively new to angular, and after hours of debugging, I found some incompatibility when adding jquery. The directive works fine without jquery, but breaks with it: /

Here is plnkr:

http://plnkr.co/edit/sRwqrWV1ha4Dp7lvsSAg?p=preview

var app = angular.module('plunker', []);

app.directive('dynamic', function ($compile) {
  return {
    restrict: 'A',
    replace: true,
    link: function (scope, ele, attrs) {
      scope.$watch(attrs.dynamic, function(html) {
        ele.html(html);
        $compile(ele.contents())(scope);
      });
    }
  };
})

app.controller('MainCtrl', function($scope, $sce, $compile) {

    $scope.trustedHtml = $sce.trustAsHtml('<button ng-click="testAlert()">Submit</button>');  

    $scope.testAlert = function () {
        alert('testing');
    };

});

+3
source share
1 answer

The problem arises because it $sce.trustAsHtmldoes not return an HTML string, and jQuery overrides the method .html.

You can fix the problem:

var app = angular.module('plunker', []);

app.directive('dynamic', function ($compile) {
    return {
        restrict: 'A',
        replace: true,
        link: function (scope, ele, attrs) {
            scope.$watch(attrs.dynamic, function (html) {
                ele.html(html.$$unwrapTrustedValue());
                $compile(ele.contents())(scope);
            });
        }
    };
})

app.controller('MainCtrl', function ($scope, $sce, $compile) {

    $scope.trustedHtml = $sce.trustAsHtml('<button ng-click="testAlert()">Submit</button>');

    $scope.testAlert = function () {
        alert('testing');
    };

});

Plunkr

NOTE . This solves the problem, but I do not consider the use of $$unwrapTrustedValuegood practice. A better solution would be to have a template that binds to attrs.dynamic.

This is the best solution: http://plnkr.co/edit/xjS9gTJfyXvTL4LNzXub?p=preview

var app = angular.module('plunker', []);

app.directive('dynamic', function ($compile) {
    return {
        restrict: 'A',
        replace: true,
        template: '<span ng-bind-html="dynamic" ng-click="method()"></span>',
        scope: {
            dynamic: '=',
            method: '&'
        }
    };
})

app.controller('MainCtrl', function ($scope, $sce, $compile) {
    $scope.trustedHtml = $sce.trustAsHtml('<button>Submit</button>');
    $scope.testAlert = function () {
        alert('testing');
    };
});

HTML

<div dynamic="trustedHtml" method="testAlert()"></div>
+1
source

All Articles