Как показать всплывающее окно angular bootstrap в пользовательском событии?

Я хочу отображать всплывающее окно начальной загрузки при настраиваемом событии (после загрузки данных с сервера). Я не понимаю, почему этот код не работает. JSFiddle

И второй вопрос, как запускать события, если я установил replace = true? Поскольку IE8 не поддерживает настраиваемые теги и выдает исключение.

<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);
                }
            };
        }
    };
}]);

person David E. Veliev    schedule 13.10.2016    source источник
comment
ваш код - беспорядок, вы смешиваете jquery с angular, а replace устарел. и вы используете старую версию ui-bootstrap. вы пробовали просмотреть примеры?   -  person svarog    schedule 13.10.2016
comment
Мне нужно использовать старые версии для ie8. Это последние версии библиотек, которые все еще поддерживают ie8. И нужно использовать replace=true (ie8 не поддерживает настраиваемые теги и выдает исключение). Как я могу связать обработчик событий и запускать события с помощью angular и без jquery (т.е. без смешивания)?   -  person David E. Veliev    schedule 13.10.2016
comment
используйте встроенные директивы angular, ng-click, ng-change и т. д.   -  person svarog    schedule 13.10.2016


Ответы (1)


Хорошо, я нашел решение.

Прежде всего, смешивание replace=true и ng-if в корневом элементе шаблона - плохая идея. Затем я разделил угловые события включения / трансляции и собственные события js. Родные события по-прежнему необходимы для всплывающего окна.

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);
                }
            };
        }
    };
}]);
person David E. Veliev    schedule 13.10.2016