简体   繁体   中英

How to show angular bootstrap popover on custom event?

I want to display bootstrap popover on custom event (after loading data from server). I don't understand why this code don't work. JSFiddle

And second question, how to trigger events if I set replace = true ? Because of IE8 doesn't support custom tags and throws exception.

<div ng-app="tcApp">
    <manual></manual>
</div>
var tcApp = angular.module('tcApp', [ 'ui.bootstrap' ]);

tcApp.config(function ($tooltipProvider) {
    $tooltipProvider.setTriggers({
        'openAfterLoad': 'closeOnClick'
    });
});

tcApp.directive('manual', [ '$timeout', '$interval', function($timeout, $interval) {
    return {
        restrict: 'E',
        scope: {},
        template: 
    '<a ' + 
'   href="#" ' + 
'   ng-if="isManualVisible" ' + 
'   popover-append-to-body="true" ' + 
'   popover-placement="bottom" ' + 
'   popover-trigger="openAfterLoad" ' + 
'   popover-title="{{title}}" ' + 
'   popover="{{content}}" ' + 
'   tooltip="{{title}}" ' + 
'   >' + 
'   <span class="{{textClass}}">' + 
'       <span ng-show="!loading" class="glyphicon glyphicon-question-sign"></span>' + 
'       <span ng-show="loading" class="glyphicon glyphicon-refresh"></span>' + 
'   </span>' + 
'</a>',
        replace: false, // true for IE8 only
        link: function (scope, element, attr) {

            scope.isManualVisible = true;
            scope.title = 'First title value';
            scope.content = 'First content value';
            scope.textClass = 'text-info';

            scope.opened = false;
            scope.loading = false;
            scope.loaded = false;
            scope.loadedTitle = false;
            scope.loadedContent = false;
            scope.checkLoadState = function () {
                if (scope.loadedTitle && scope.loadedContent) {
                    scope.loaded = true;
                    if (scope.loading)
                        scope.loading = false;
                    element.triggerHandler('openAfterLoad');
                }
            };
            scope.$watch('loadedTitle', scope.checkLoadState);
            scope.$watch('loadedContent', scope.checkLoadState);

            element.on('openAfterLoad', function(event) {
                console.log('openAfterLoad');
                scope.opened = true;
            });

            element.on('closeOnClick', function(event) {
                console.log('closeOnClick');
                scope.opened = false;
            });

            element.on('click', function(event) {
                console.log('click');
                if (scope.loaded) {
                    if (scope.opened)
                        element.triggerHandler('closeOnClick');
                    else
                        element.triggerHandler('openAfterLoad');
                } else {
                    scope.loadData();
                }
            });

            scope.loadData = function() {
                if (!scope.loaded && !scope.loading) {
                    scope.loading = true;

                    $interval(function() {
                        scope.title = 'New title value';
                        scope.loadedTitle = true;
                    }, 5000, 1);

                    $interval(function() {
                        scope.content = 'New content value';
                        scope.loadedContent = true;
                    }, 5000, 1);
                }
            };
        }
    };
}]);

Ok, I'm found solution.

First of all, mixing of replace=true and ng-if on root template element is a bad idea. Next, I separated angular on/broadcast events and native js events. Native events still required for popover.

JSFiddle

<div ng-app="tcApp">
    <manual></manual>
</div>
var tcApp = angular.module('tcApp', [ 'ui.bootstrap' ]);

tcApp.config(function ($tooltipProvider) {
    $tooltipProvider.setTriggers({
        'openAfterLoad': 'closeOnClick'
    });
});

tcApp.directive('manual', [ '$timeout', '$interval', function($timeout, $interval) {
    return {
        restrict: 'E',
        scope: {},
        template: 
    '<a ' + 
'   href="#" ' + 
'   ng-show="isManualVisible" ' +
'   ng-click="clickHandler()" ' +
'   popover-append-to-body="true" ' + 
'   popover-placement="bottom" ' + 
'   popover-trigger="openAfterLoad" ' + 
'   popover-title="{{title}}" ' + 
'   popover="{{content}}" ' + 
'   tooltip="{{title}}" ' + 
'   >' + 
'   <span class="{{textClass}}">' + 
'       <span ng-show="!loading" class="glyphicon glyphicon-question-sign"></span>' + 
'       <span ng-show="loading" class="glyphicon glyphicon-refresh"></span>' + 
'   </span>' + 
'</a>',
        replace: true, // true for IE8 only
        link: function (scope, element, attr) {

            scope.isManualVisible = true;
            scope.title = 'First title value';
            scope.content = 'First content value';
            scope.textClass = 'text-info';

            scope.opened = false;
            scope.loading = false;
            scope.loaded = false;
            scope.loadedTitle = false;
            scope.loadedContent = false;
            scope.checkLoadState = function () {
                if (scope.loadedTitle && scope.loadedContent) {
                    scope.loaded = true;
                    if (scope.loading)
                        scope.loading = false;
                    scope.$broadcast('openAfterLoad');
                }
            };
            scope.$watch('loadedTitle', scope.checkLoadState);
            scope.$watch('loadedContent', scope.checkLoadState);

            scope.$on('openAfterLoad', function(event) {
                console.log('openAfterLoad');
                scope.opened = true;
                $timeout(function() {
                    // trigger popover
                    element.triggerHandler('openAfterLoad');
                });
            });

            scope.$on('closeOnClick', function(event) {
                console.log('closeOnClick');
                scope.opened = false;
                $timeout(function() {
                    // trigger popover
                    element.triggerHandler('closeOnClick');
                });
            });

            scope.clickHandler = function(event) {
                console.log('click');
                if (scope.loaded) {
                    if (scope.opened)
                        scope.$broadcast('closeOnClick');
                    else
                        scope.$broadcast('openAfterLoad');
                } else {
                    scope.loadData();
                }
            };

            scope.loadData = function() {
                if (!scope.loaded && !scope.loading) {
                    scope.loading = true;

                    $interval(function() {
                        scope.title = 'New title value';
                        scope.loadedTitle = true;
                    }, 2000, 1);

                    $interval(function() {
                        scope.content = 'New content value';
                        scope.loadedContent = true;
                    }, 3000, 1);
                }
            };
        }
    };
}]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM