27

I have an Angular directive to handle Bootstrap popovers as shown in the code below. In my directive I'm setting the popover content to a HTML string, which I think is ugly. What I wanna do is to use an "template.html" file instead of HTMLstring. In that way I will be able to use the same directive with different template files depending on which type of popover I wanna show. That's my plan anyway.

So, how do I in the best way load html code from my template.html and use it instead of the HTMLstring in the AngularJs directive below?

app.directive('mypopover', function ($compile) {

var HTMLstring = "<div><label class='control-label' style='color: rgb(153, 153,153)'>Search</label>&nbsp;&nbsp;"+"<input placeholder='Search assignment' ng-model='searchText' type='text' class='form-control'> <br>"+"<label class='control-label' style='color: rgb(153, 153, 153)'>Select an assignable</label>"+"<p ng-repeat='p in projects | filter:searchText'ng-click='createEvent(user.id,date)'>"+"{{p.title}}</p></div>";

var getTemplate = function (contentType) {
    var template = '';
    switch (contentType) {
        case 'user':
            template = HTMLstring;
            break;
    }
    return template;
}
return {
    restrict: "A",
    link: function (scope, element, attrs) {
        var popOverContent;
        if (scope.user) {
            var html = getTemplate("user");
            popOverContent = $compile(html)(scope);                    
        }
        var options = {
            content: popOverContent,
            placement: "right",
            html: true,
            date: scope.date
        };
        $(element).popover(options);
    },
    scope: {
        user: '=',
        date: '='
    }
};
});

2 Answers 2

20

A quick solution is using templateCache with inline template:

Inline template:

<script type="text/ng-template" id="templateId.html">
      This is the content of the template
</script>

Js:

app.directive('mypopover', function ($compile,$templateCache) {

    var getTemplate = function (contentType) {
        var template = '';
        switch (contentType) {
            case 'user':
                template = $templateCache.get("templateId.html");
                break;
        }
        return template;
    }

DEMO

If you need to load external templates, you need to use ajax $http to load the templates manually and put in the cache. Then you can use $templateCache.get to retrieve later.

$templateCache.put('templateId.html', YouContentLoadedUsingHttp);

Sample code:

var getTemplate = function(contentType) {
    var def = $q.defer();

    var template = '';
    switch (contentType) {
      case 'user':
        template = $templateCache.get("templateId.html");
        if (typeof template === "undefined") {
          $http.get("templateId.html")
            .success(function(data) {
              $templateCache.put("templateId.html", data);
              def.resolve(data);
            });
        } else {
           def.resolve(template);
        }
        break;
    }
    return def.promise;
  }

DEMO

Sign up to request clarification or add additional context in comments.

15 Comments

This works perfect, however is it possible to use angularjs expressions into the template?? I mean something like this: <script type="text/ng-template" id="templateId.html">{{ $scope.name }}</script>
@joselo: Yes, it is. In this case we have to compile it popOverContent = $compile("<div>" + popOverContent+"</div>")(scope);. See demo plnkr.co/edit/CoDdWWQz8jPPM4q1mhC5?p=preview
In the above case, it is assumed that the content of popover is fixed(template.html). What if I want to use different content for different popovers? Something like an attribute passed from html to show different template. a href pop-over items="items" title="someTitle" template="location/of/anotherTemplate.html" >Show Another Pop over</a> In this case, $templateCache won't store the second template. Loading over $http doesn't help being asynchronous.
@Aniket Sinha: You could load location/of/anotherTemplate.html using $http or use inline template. Then handle the click event of the <a> to display the popover.
@Aniket Sinha: See my updated answer. Hope it helps.
|
4

To complete the answer from Khahn, if you load a dynamic template, the last part should look like that:

return {
restrict: "A",
scope: {
    item: "=" // what needs to be passed to the template
},
link: function(scope, element, attrs) {

  getTemplate("user").then(function(popOverContent) {

    var options = {
      content: $compile($(popOverContent))(scope),
      placement: "bottom",
      html: true,
      trigger: "hover"
    };
    $(element).popover(options);

  });
}

};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.