Javascript 角度自定义指令-$scope.$watch未触发

Javascript 角度自定义指令-$scope.$watch未触发,javascript,angularjs,angularjs-directive,angularjs-scope,Javascript,Angularjs,Angularjs Directive,Angularjs Scope,我正在尝试制作一个下拉指令,使用Angular UI代码获得灵感 我可以让它在打开和关闭下拉列表的意义上工作,但我已经尝试扩展它,以便“dropdownManager”服务可以关闭页面上的所有下拉列表,并且可以使用页面控制器代码打开和关闭它 为此,我创建了一个名为“is open”的属性,并在其上放置了一个角度表。不幸的是,当控制器更新属性时,或者当范围变量从指令自身的打开/关闭函数更新时,此监视不会触发。我知道这个值正在改变,因为否则下拉列表将无法打开和关闭,但手表肯定不是foring,因为它

我正在尝试制作一个下拉指令,使用Angular UI代码获得灵感

我可以让它在打开和关闭下拉列表的意义上工作,但我已经尝试扩展它,以便“dropdownManager”服务可以关闭页面上的所有下拉列表,并且可以使用页面控制器代码打开和关闭它

为此,我创建了一个名为“is open”的属性,并在其上放置了一个角度表。不幸的是,当控制器更新属性时,或者当范围变量从指令自身的打开/关闭函数更新时,此监视不会触发。我知道这个值正在改变,因为否则下拉列表将无法打开和关闭,但手表肯定不是foring,因为它里面有一个console.log

奇怪的是,由于console.log被写入,所以当它第一次初始化时,它会为页面上的每个下拉菜单触发一次

不管怎么说,我想做一把小提琴,但有太多的依赖关系,对不起,但我已经设法减少了代码尽可能多,所以希望它应该是一个经验丰富的用户很容易理解

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


        }        

    };

});

一次关闭和打开所有下拉列表的一个好方法是使用事件:

$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是在不同的范围内定义的。

好的,所以我最终自己找到了答案

这:

需要成为:

$element.find('[dropdown-toggle]').bind('click', function(){
    $scope.$apply($scope.toggleDropdown);
});
我假设这是因为jqueryclick事件发生在“角度世界之外”,所以将其包装在apply中会导致摘要循环发生在单击之后,然后触发手表


不过,不要相信我的话。我说的是文字,但我真的不知道它们是什么意思。

当然指令本身中的所有内容都不需要“名称空间”,因为它们都直接在$scope上?哪一位需要使用xxx.yyy?哦,看起来注释被删除了。它越来越长,所以我将它移到了一个答案。谢谢你的回答,Alex,但我想在指令内做所有事情(实际上我正在使用管理器服务来处理指令之间的通信)。我真的很想了解为什么我的手表不工作,而不是找到一个解决办法。谢谢。请检查此项,如果从服务调用“isOpen”变量,您可能会遇到相同的问题:是否可以尝试
angular.element(document.querySelectorAll(“[dropdown toggle]”)。on('click',function(){$scope.toggleDropdown();})并说明它是否与第二个代码段具有相同的效果,使用.on而不是.bind似乎有效,但不确定原因,尽管您的代码会影响页面上的所有内容。我也做到了。
$element.find('[dropdown-toggle]').bind('click', function(){
    $scope.$apply($scope.toggleDropdown);
});