AngularJS - 范围监视不会在更新ng-class时触发

时间:2013-11-27 16:11:22

标签: angularjs angularjs-directive

我正在尝试使用Angular实现下拉菜单,如果用户点击链接1,则应显示链接1的内容。我的指示如下:

  1. 移动菜单,用作控制器并跟踪链接和菜单项状态
  2. menu-link,用户点击以打开/关闭菜单项的实际链接
  3. menu-item,应根据scope.test值显示/隐藏的菜单项
  4. 这是我的AngularJS代码:

    angular.module("myApp", [])
    .controller("testCtrl", function ($scope) {})
    .directive("mobileMenu", function () {
        return {
            controller: function ($scope) {
                this.menuLinks = [];
                this.menuItems = [];
    
                this.addMenuLink = function (l) {
                    this.menuLinks.push(l);
                };
                this.addMenuItem = function (m) {
                    this.menuItems.push(m);
                };
                // Function to close all other menu items if they are open.
                // This is because only one menu item can be active at a time
                this.closeOthers = function (selectedMenuLink) {
    
                    angular.forEach(this.menuLinks, function (l) {
                        if (l !== selectedMenuLink) {
                            l.selected = false;
                        } 
                    }); 
    
                    angular.forEach(this.menuItems, function (m) {
                        if (selectedMenuLink.target == m.menuId) {
                            m.test = true;
                        } else {
                            m.test = false;
                        }
                    });
                };
            }
        };
    }).directive("menuLink", function () {
        return {
            require: "^mobileMenu",
            scope: {},
            link: function(scope, element, attrs, menuController) {
                    scope.selected = false;
            menuController.addMenuLink(scope);
    
            scope.$watch('selected', function(newValue, oldValue) {
                if (oldValue === newValue) {return};
    
                if (newValue) {
                    scope.target = angular.element(element[0].children[0]).attr("data-menu");
                    menuController.closeOthers(scope);
                }
             });
           }
        };
    }).directive("menuItem", function () {
        return {
            require: "^mobileMenu",
            scope: true,
            link: function (scope, element, attrs, menuController) {
    
                scope.test = false;
                scope.menuId = attrs.id;
                menuController.addMenuItem(scope);
    
                scope.$watch('test', watchLink);
                scope.$watch(attrs.collapse, watchLink);
                scope.$watch(function () {
                    return scope.test;
                }, watchLink);
    
                var watchLink = function (newValue, oldValue) {
    
                    // Initializing for the first time, do nothing
                    if (newValue === oldValue) return;
    
    
                    // If the collapse attribute has a true value, collapse this element
                    if (newValue) {
                        collapse();
                    } else {
                        expand();
                    }
                };
    
                // Helper function to collapse the element
                var collapse = function () {
                    element.css({
                        height: "0px"
                    });
                };
    
                // Helper function to show the element
                var expand = function () {
                    element.css({
                        height: "200px"
                    });
                };
            }
        };
    });
    

    这是我的HTML代码:

    <div ng-app="myApp" ng-controller="testCtrl">
    <div mobile-menu>
        <ul> 
            <li menu-link>
                <a href="#" ng-click="selected = !selected" ng-class="{'expanded' : selected, 'collapsed' : !selected}" data-menu="menu0">Link 1</a>
            </li>
    
             <li menu-link>
                 <a href="#" ng-click="selected = !selected" ng-class="{'expanded' : selected, 'collapsed' : !selected}" data-menu="menu1">Link 2</a>
            </li>
        </ul>
        <div id="menu0" ng-class="{'expanded' : test, 'collapsed' : !test}" menu-item collapse="!test">
            <p class="text">First Menu</p>
        </div>
        <div id="menu1" ng-class="{'expanded' : test, 'collapsed' : !test}" menu-item collapse="!test">
            <p class="promo-text">Second Menu</p>
        </div>
    </div>
    

    我遇到一个问题,如果单击菜单链接#1,应该更新相应的菜单项#1的scope.test值,并且应该触发其“范围监视”,但事实并非如此。如果示波器监视触发了watchLink功能,那么我希望菜单项#1的高度为200px。

    我还附上了一个jsfiddle示例: http://jsfiddle.net/EmwBP/28/

    如果查看浏览器控制台工具,相应的菜单项ng-class将始终根据其scope.test值进行更新。然而,即使我设置了3个不同的范围观察者,也没有一个被触发。我也使用ng-class指令只是为了表明scope.test值确实已更新,并将在最终实现中删除。

    通常情况下,我会将菜单项指令作为菜单链接的子项,但我有一个要求,我现在必须放置菜单项,以实现推送的下拉效果它下面的元素。

    非常感谢您的意见和协助

1 个答案:

答案 0 :(得分:1)

使用menuLinkscope: {}中创建新的隔离范围。因此,您在该范围内设置的任何范围变量(如selected)仅在该范围内可用,并且不会传播到兄弟范围或父范围。

您需要做的是使用menuLink去隔离scope: true范围。


这不是问题。问题是在定义watchLink之前使用watchLink。修复触发{{1}}的位置:http://jsfiddle.net/EmwBP/31/