0

Я пытаюсь создать директиву выпадающего списка, используя код Углового UI для вдохновения.

Я могу заставить его работать в том смысле, что он открывает и закрывает выпадающий список, но я попытался его расширить, чтобы служба «dropdownManager» могла закрыть все выпадающие списки на странице и открыть ее и закрывается с использованием кода контроллера страницы.

Для этого я создал атрибут под названием «is-open» и поставил на него угловые часы. К сожалению, эти часы не срабатывают, когда атрибут обновляется контроллером или когда переменная scope обновляется из собственных функций открытия/закрытия директивы. Я знаю, что значение меняется, потому что в противном случае выпадающее меню не будет открываться и закрываться, но часы определенно не вызывают, потому что внутри него есть console.log.

Странно, что он срабатывает один раз для каждого выпадающего списка на странице, когда он сначала инициализируется, потому что console.log записывается!

В любом случае, я стараюсь сделать скрипку, но слишком много зависимостей, извините, но мне удалось максимально уменьшить код, поэтому, надеюсь, для опытного пользователя Angular это должно быть очень легко понять.

angular.module('directives').directive('dropdown', function() { 

    return { 

     restrict: 'EA', 
     scope: { 
      isOpen: '=?', 
     }, 

     link: function ($scope, $element, $attrs, ngModel) { 


      // Defaults 
      $scope.isOpen = false; 

      // Watch the isOpen variable 
      $scope.$watch('isOpen', function(value) { 

       console.log("Scope Changed", $scope.isOpen); 

       // Open or close this panel 
       if (value === true){ 
        $scope.openDropdown(); 
       } 
       else{ 
        $scope.closeDropdown(); 
       } 

      });    


      // Open Dropdown 
      $scope.openDropdown = function($event){ 

       $scope.isOpen = true; 

       var panelEl = $element.find('[dropdown-panel]'); 

       panelEl.slideDown(100, function(){ 
        $element.addClass('is-open'); 
       }); 

      }; 



      // Open Dropdown 
      $scope.closeDropdown = function($event){ 

       $scope.isOpen = false; 

       var panelEl = $element.find('[dropdown-panel]'); 

       $element.removeClass('is-open'); 

       panelEl.slideUp(100); 

      }; 


      // Toggle Dropdown 
      $scope.toggleDropdown = function ($event) { 

       if(!$scope.isOpen){ 
        $scope.openDropdown(); 
       } 

       else{ 
        $scope.closeDropdown(); 
       } 

      }; 


      // Add click event to toggle element 
      $element.find('[dropdown-toggle]').bind('click', $scope.toggleDropdown); 


     }   

    }; 

}); 
+0

Несомненно, все, что находится внутри самой директивы, не нуждается в «namespacing», потому что все это прямо на $ scope? Какой бит нужно использовать xxx.yyy? – jonhobbs

+0

О, похоже, комментарий удален. – jonhobbs

+0

Получилось долго, поэтому я перевел его на ответ. – 7stud

ответ

0

ОК, поэтому я нашел ответ сам в конце.

Это:

$element.find('[dropdown-toggle]').bind('click', $scope.toggleDropdown); 

Необходимо, чтобы стать:

$element.find('[dropdown-toggle]').bind('click', function(){ 
    $scope.$apply($scope.toggleDropdown); 
}); 

Я предполагаю, что это потому, что Jquery нажмите событие происходит «за пределами углового мира», так оборачивать его в применяются причины дайджеста цикл после нажатия, который затем запускает часы.

Не говорите ни слова об этом. Я говорю слова, но я понятия не имею, что они означают.

+0

вы можете попробовать 'angular.element (document.querySelectorAll ('[dropdown-toggle]')). on ('click', function() {$ scope.toggleDropdown(); }); 'и скажем, если он имеет тот же эффект, что и ваш второй фрагмент. –

+0

Использование .on, а не .bind, похоже, работает, не зная почему, хотя ваш код повлияет на все на странице. Мне удалось заставить это работать и так. – jonhobbs

0

Хороший вариант, чтобы закрыть и открыть все выпадающие на один раз, чтобы использовать события:

$scope.$on('close all modals', function(){ 
    $scope.isOpen = false; 
}) 

$scope.$on('open all modals', function(){ 
    $scope.isOpen = true; 
}) 

, а затем, когда вы хотите, чтобы закрыть все, везде, где в вашем коде вы можете позвонить:

$rootScope.$broadcast('close all modals'); 

Причина, по которой ваши часы вызывается один раз, вероятно, потому, что isOpen изменяется с неопределенного на false. Я думаю, ваша проблема в том, что isOpen определяется в разных областях.

+0

Спасибо за ваш ответ Алекс, но я хотел сделать все внутри директивы (и я фактически использую сервис-менеджер для управления связью между директивами). Я действительно хотел понять, почему мои часы не работают, чем найти обходной путь. Благодарю. – jonhobbs

+0

Проверьте, это может быть проблема, если ваша переменная isOpen вызывается из службы: http://stackoverflow.com/questions/21640459/angularjs-variables-in-service-not-updating-for-service- или -контроллер – AlexHv

Смежные вопросы