Search code examples
javascriptangularjsangularjs-directiveangular-bootstrap

How to use dynamic html with a directive that injects an angular bootstrap popover?


I am trying to write a directive that returns an uib angular bootstrap html popup populated with html from an external source.

Envisaged usage:

<b help-pop="title1"> Title 1</b>

I am unable to do so since uib-popover-html expects an "expression that evaluates to an HTML string" and not the HTML string itself

help_texts = {title1:"This is <b>text</b> for <br> title 1", 
          title2: "This is text for title 2"
 }

var app = angular.module('popTest',['ui.bootstrap']);
app.controller('popCtrl', function ($scope, $sce) {});
app.directive('helpPop', function ($compile, $sce) {
 return {

  restrict: 'A',
  replace: false, 
  terminal: true, 
  priority: 1000, 
  compile: function compile(element, attrs) {        

    // plaintext works great for non-html
    //it = help_texts[attrs.helpPop]
    //element.attr('uib-popover', it);

    /* 
    This does not work since uib-popover-html "Takes an expression that 
    evaluates to an HTML string" and not the HTML-string itself
    ref https://angular-ui.github.io/bootstrap/
    */
    it = $sce.trustAsHtml(help_texts[attrs.helpPop]);
    element.attr('uib-popover-html', it);

    element.attr('popover-placement', 'auto top');
    element.attr('popover-trigger', 'mouseenter');
    element.addClass('helptxt');
    element.removeAttr("help-pop"); 
    element.removeAttr("data-help-pop"); 
    return {
      pre: function preLink() {},
      post: function postLink(scope, ie) {  
        $compile(ie)(scope);
      }
    };
  }
};
});

Does anyone have any suggestions on how to make this work?

Plunker


Solution

  • I found a workaround using "uib-popover-template" instead of "uib-popover-html":

    help_texts = { 
              title1:"This is <b>text</b> for <br> title 1", 
              title2: "This is <i>text</i> for title 2"
    }
    
    var app = angular.module('popTest',['ui.bootstrap']);
    app.controller('popCtrl', function ($scope, $sce) {});
    app.directive('helpPop', function ($compile, $sce) {
    return {
    
      restrict: 'A',
      replace: false, 
      terminal: true, 
      priority: 1000, 
      scope: {},
      compile: function compile(element, attrs) {        
    
        element.attr('uib-popover-template', "'popover.html'");
    
        element.attr('popover-placement', 'auto top');
        element.attr('popover-trigger', 'mouseenter');
        element.addClass('helptxt');
        element.removeAttr("help-pop"); 
        element.removeAttr("data-help-pop"); 
        return {
          pre: function preLink() {},
          post: function postLink(scope, ie) {  
            $compile(ie)(scope);
            scope.poptext = $sce.trustAsHtml(help_texts[attrs.helpPop]); 
          }
        };
      }
    };
    });
    

    A template needs to be added to the DOM:

    <script type="text/ng-template" id="popover.html">
      <div ng-bind-html='poptext'></div>
    </script>
    

    Updated plunker