Getting ng-repeat to work inside of AngularJS's $interpolate service

前端 未结 1 563
夕颜
夕颜 2021-01-05 01:32

I am using the AngularJs-UI components for Bootstrap. I would like to insert a filled out template into one of the data elements for the popover feature. This works find for

相关标签:
1条回答
  • 2021-01-05 01:59

    $interpolate doesn't handle directives like ngRepeat ( Difference between parse, interpolate and compile ). $interpolate:

    Compiles a string with markup into an interpolation function. This service is used by the HTML $compile service for data binding.

    To handle ngRepeat and other directives you want $compile. But for your use case $compile is going to result, unfortunately, in a number of changes because:

    • It needs a scope to compile against rather than just a context like $interpolate. Moreover it needs the scope thingy is on.

      This means we'll need to reference your properties like so {{thingy.blah}} instead of {{blah}} inside your template.

    • The compile needs to happen when the popup is on the dom.

    • The popup is only on the dom when it's open.

    So we can't just replace $interpolate with $compile inside your service.

    One approach is to replace data-ng-bind-html with the following directive that acts like an ng-bind-html that has a built in $compile (clearly you should only use this with html that you know is safe).

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

    Used like so (with compile replacing ng-bind-html:

      <div class="popover-content" compile="content"></div>
    

    One issue is that we need thingy to be in scope. There's a few of ways of handling that- but for demonstration purposes I've manually gone back up to the scope the popover is called from - which is 2 scopes up thus the scope.$parent.$parent.

    Using this compile directive you no longer $interpolate or $sanitizeso the function in your service can shrink down to just returning the appropriate template:

    function html_for() {
      var template = $templateCache.get('thingyTemplate.html');
      return template;
    }
    

    demo fiddle

    0 讨论(0)
提交回复
热议问题