Пользовательская директива AngularJS bootstrap popover

Я создал директиву, использующую пользовательскую посылку bootstrap. Это работает с вводом пользователя от имени группы, и у него есть две кнопки для применения этого значения для моделирования и отображения этого значения в подсказке и кнопки для закрытия popover. Я использую popover java script события, проблема в том, что single popover отлично работает, но когда я открываю другой, этот popover не закрывается сам. Нужна помощь в закрытии других popovers, пока один открыт. Ниже приведена директива plnk.

Вот код

var app = angular.module('myApp',[]);
app.directive('customEditPopover', function () {
        return {
            restrict: 'A',
            template: '<span><i class="fa fa-tags" aria-hidden="true"></i></span>',
            scope: {
                'myModel': '=',
            },
            link: function (scope, el, attrs) {
                scope.label = attrs.popoverLabel;
                var btnsave = '#' + attrs.popoverSave;
                var btncancel = '#' + attrs.popoverCancel;
                var index = attrs.index;
                $(el).tooltip({
                    title: '' + (scope.myModel == undefined) ? "" : scope.myModel,
                    container: 'body',
                    placement: 'top'
                });
                $(el).popover({
                    trigger: 'click',
                    html: true,
                    content: attrs.popoverHtml,
                    placement: attrs.popoverPlacement,
                    container: 'body'
                })
                .on('inserted.bs.popover', function (e) {
                    bindevents();
                    $('#popovertext' + index).val(scope.myModel);
                }).on('hidden.bs.popover', function () {
                    Unbindevents();
                });
                function bindevents() {
                    $(btnsave).bind('click', function () {
                        var text = $('#popovertext' + index).val();
                        scope.myModel = text;
                        $(el).tooltip('hide')
                       .attr('data-original-title', text)
                       .tooltip('fixTitle')
                        toggle();
                    });
                    $(btncancel).bind('click', function () {
                        toggle();
                    });
                }
                function Unbindevents() {
                    $(btnsave).unbind('click');
                    $(btncancel).unbind('click');
                }
                function toggle() {
                    $(el).popover('hide');
                    $(el).click();
                }

            }
        };
    });
app.controller('MyController',['$scope',function($scope){
  $scope.list=[
    {
      name:'ABC'
    },
     {
      name:'DEF'
    },
     {
      name:'GHI'
    },
     {
      name:'KLM'
    }
    ];

}]);

Нужна помощь в закрытии другого popover при открытии следующего.

Ответ 1

Вы можете закрыть другие popovers, когда show.bs.popover запускается, как показано ниже: Обновлено Plunkr

$(el).popover({
                trigger: 'click',
                html: true,
                content: attrs.popoverHtml,
                placement: attrs.popoverPlacement,
                container: 'body'
            })
             .on('show.bs.popover', function () {
              var siblings = $(el).parent().parent().siblings();
              siblings.each(function (each){
                $(siblings[each]).find('span').popover('hide');
              });
            });

Ответ 2

IMO, самым модульным способом было бы использовать сервис для отслеживания всех открытых PopUps.

Это дает несколько преимуществ.

  • Вы можете расширить службу, чтобы отслеживать различные типы всплывающих окон, позволяя закрыть все или открыть все или сделать все, что вам нужно.

  • Он удаляет логику из элементов управления и директив при отслеживании всплывающих окон. Таким образом, они могут сосредоточиться на одной конкретной вещи. Вы также можете запускать несколько контроллеров и всплывающих окон на странице, чтобы каждый контроллер/всплывающее окно являлся дискретной единицей работы и не нуждался в том, чтобы беспокоиться о том, что другие контроллеры/всплывающие окна топают по своим элементам.

Недостатки этого

  • Как я уже говорил ранее, для этого можно использовать angular директивы bootstrap. Сделайте свой код "чище", потому что все это сделано для вас. Что не сделано для вас, это закрытие всех активных всплывающих окон. Вы можете использовать тот же подход к сервису, который я использовал, и просто подключить его к директивам ng-bootstrap.
  • Связывание/Отмена событий JQUERY, похоже, перестает отвечать на запросы, когда вы нажимаете 8+ раз. У меня нет ответа, почему это так, но общая идея использования сервиса для отслеживания остается действительной.

Вы можете разрезать и вставлять этот код в plnkr или в свой dev-блок, и он будет работать.

// Code goes here
var app = angular.module('myApp',[]);

app.factory('popUpService', function() {
  var activePopups = [];
  // factory function body that constructs shinyNewServiceInstance

  return {
  AddPopup : function(el)
  {
  activePopups.push(el);
  },
  CloseAllPopups : function(closeFunction){
  for (var i = 0; i < activePopups.length; i++)
  { 
           closeFunction(activePopups[i])

  }
  }
  }

});
app.directive('customEditPopover',['popUpService', function (popUpService) {
        return {
            restrict: 'A',
            template: '<span><i class="fa fa-tags" aria-hidden="true"></i></span>',
            scope: {
                'myModel': '=',
            },
            link: function (scope, el, attrs) {
                scope.label = attrs.popoverLabel;
                var btnsave = '#' + attrs.popoverSave;
                var btncancel = '#' + attrs.popoverCancel;
                var index = attrs.index;
                $(el).tooltip({
                    title: '' + (scope.myModel == undefined) ? "" : scope.myModel,
                    container: 'body',
                    placement: 'top'
                });
                $(el).popover({
                    trigger: 'click',
                    html: true,
                    content: attrs.popoverHtml,
                    placement: attrs.popoverPlacement,
                    container: 'body'
                })
                .on('inserted.bs.popover', function (e) {
                    bindevents();
                    $('#popovertext' + index).val(scope.myModel);
                }).on('hidden.bs.popover', function () {
                    Unbindevents();
                });
                function bindevents() {

                CloseAll();

                popUpService.AddPopup($(el));

                    $(btnsave).bind('click', function () {
                        var text = $('#popovertext' + index).val();
                        scope.myModel = text;
                        $(el).tooltip('hide')
                       .attr('data-original-title', text)
                       .tooltip('fixTitle')
                    closeCurrent();
                    });
                    $(btncancel).bind('click', function () {
                    closeCurrent();
                    });
                }
                function Unbindevents() {
                    $(btnsave).unbind('click');
                    $(btncancel).unbind('click');
                }
                function closeCurrent(){
                   $(el).popover('hide');
                 //   $(el).click();
                }
                function CloseAll() {

                popUpService.CloseAllPopups(function(popup){ 

                   popup.popover('hide');
                //    popup.click();
              });

            }
        }
        }
    }]);
app.controller('MyController',['$scope',function($scope){
  $scope.list=[
    {
      name:'ABC'
    },
     {
      name:'DEF'
    },
     {
      name:'GHI'
    },
     {
      name:'KLM'
    }
    ];

}]);