MrViSiOn
MrViSiOn

Reputation: 191

ng-bind-html and ng-controller

I'm injecting insecure html into some <div>, like this:

<div class="category-wrapper" ng-bind-html="content"></div>

this html has angularjs "code" ($scope.content is loaded with something like this):

<script type='text/javascript' src='giveus.js'></script>
<div class="giveus-wrapper" ng-controller="GiveUsController">{{variable1}}</div>

Note that this snippet has ng-controller. GiveUsController is lazy loaded at the same time that the embedded html (not in head). There is no error declaring this controller because It has been already tested.

My controller is as easy as:

angular.module("tf").controller('GiveUsController', function ($scope, $http)    
{
     console.debug("GiveUsController loaded");
     $scope.variable1 = "hi!";
}

there is no console debug nor variable1 assignment

It looks like there is no controller binding to that <div>.

I don't know how I can inject html with angular controller and make it work...

Any idea?

Upvotes: 3

Views: 2328

Answers (3)

scniro
scniro

Reputation: 16979

You could do what you are wanting with a bit of manual html compilation. Here is an approach that is essentially a directive wrapper for the $compile service. Observe the following example and usage...

 <div class="category-wrapper" ng-html="content"></div>

.controller('ctrl', function($scope) {
    $scope.content = '<div class="giveus-wrapper" ng-controller="GiveUsController">{{variable1}}</div>'
})
.controller('GiveUsController', function($scope) {

    console.log('hello from GiveUsController')
    $scope.variable1 = 'I am variable 1'
})
.directive('ngHtml', ['$compile', function ($compile) {
    return function (scope, elem, attrs) {
        if (attrs.ngHtml) {
            elem.html(scope.$eval(attrs.ngHtml));
            $compile(elem.contents())(scope);
        }
        scope.$watch(attrs.ngHtml, function (newValue, oldValue) {
            if (newValue && newValue !== oldValue) {
                elem.html(newValue);
                $compile(elem.contents())(scope);
            }
        });
    };
}]);

JSFiddle Link - demo

Upvotes: 4

davesnx
davesnx

Reputation: 384

Angular for itself don't bind the ng-directives that are added into the DOM.

The $sce.compile or $compile helps angular to read which elements are added into the actual DOM, also for use the $compile you must use a directive.

Should be like that:

var m = angular.module(...);

m.directive('directiveName', function factory(injectables) {
  return = {
    priority: 0,
    template: '<div></div>', // or // function(tElement, tAttrs) { ... },
    transclude: false,
    restrict: 'A',
    templateNamespace: 'html',
    scope: false,
    controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
    controllerAs: 'stringIdentifier',
    bindToController: false,
    require: 'siblingDirectiveName', 'optionalDirectiveName', '?^optionalParent'],
    compile: function compile(tElement, tAttrs, transclude) {
      return {
        pre: function preLink(scope, iElement, iAttrs, controller) { ... },
        post: function postLink(scope, iElement, iAttrs, controller) { ... }
      }
    },

  };
});

and where you want

$compileProvider.directive('compile', function($compile) {
      return function(scope, element, attrs) {
        scope.$watch(
          function(scope) {
            return scope.$eval(attrs.compile);
          },
          function(value) {
            element.html(value);
            $compile(element.contents())(scope);
          }
        );
      };

Upvotes: 1

Ismael Fuentes
Ismael Fuentes

Reputation: 250

You have to compile the HTML content, i got this using a directive:

.directive('comunBindHtml', ['$compile', function ($compile) {
        return function(scope, element, attrs) {
          scope.$watch(
            function(scope) {
              // watch the 'compile' expression for changes
              return scope.$eval(attrs.compile);
            },
            function(value) {
              // when the 'compile' expression changes
              // assign it into the current DOM
              element.html(value);

              // compile the new DOM and link it to the current
              // scope.
              // NOTE: we only compile .childNodes so that
              // we don't get into infinite loop compiling ourselves
              $compile(element.contents())(scope);
            }
        );
      };
    }])

Hope it helps :)

Upvotes: 0

Related Questions