$ watch不更新范围变量

时间:2014-07-31 11:23:59

标签: angularjs watch

首先,我想说我是AngularJS的初学者,只是试图理解基本概念。我有Java和PHP的背景。

我正在建立一个网站的一部分。现在,角度应用程序只包括打开和关闭2下拉菜单registrationDropDown和loginDropDown。我希望它们能够工作,这样一次只能打开一个,即。如果我打开一个,另一个已打开,则旧的一个被迫关闭。

我有一个服务来管理确定下拉列表是打开还是关闭的变量,以及2个控制器,一个用于登录,一个用于注册,两个都包含$ watch来查看相应的变量。

问题 我希望应用程序能够正常工作,以便一次只能打开一个下拉菜单。

JSFIDDLE:http://jsfiddle.net/F5p6m/3/

    angular.module("ftApp", [])
    .factory('dropDownService', function () {
    var loginDropDownStatus = false;
    var registrationDropDownStatus = false;

    return {
        getLoginDropDownStatus: function () {
            return loginDropDownStatus;
        },
        showLoginDropDown: function () {
            console.log("showing login drop down");
            registrationDropDownStatus = false;
            loginDropDownStatus = true;
            console.log("loginDropDownStatus" + loginDropDownStatus + "registrationDropDownStatus" + registrationDropDownStatus);
        },
        hideLoginDropDown: function () {
            console.log("hiding login drop down");
            loginDropDownStatus = false;
            console.log("loginDropDownStatus" + loginDropDownStatus);

        },
        getRegistrationDropDownStatus: function () {
            return registrationDropDownStatus;
        },
        showRegistrationDropDown: function () {
            console.log("showing registration drop down");
            registrationDropDownStatus = true;
            loginDropDownStatus = false;
            console.log("registrationDropDownStatus" + registrationDropDownStatus);
        },
        hideRegistrationDropDown: function () {
            console.log("hiding registration drop down");
            registrationDropDownStatus = false;
            console.log("registrationDropDownStatus" + registrationDropDownStatus);
        }
    };

}) .controller("LoginDropDownController", function ($scope, dropDownService) {
        $scope.loginDropDownStatus = dropDownService.getLoginDropDownStatus();

        $scope.$watchCollection('loginDropDownStatus', function(newValue, oldValue) {
            console.log("watcher is working");
            console.log("value is " + newValue + oldValue);

            console.log("LOGIN new value is " + newValue);
            $scope.loginDropDownStatus = newValue;
        });

        $scope.toggleDropDown = function () {

            if ( $scope.loginDropDownStatus == false ) {
                dropDownService.showLoginDropDown();
                dropDownService.hideRegistrationDropDown();
                $scope.loginDropDownStatus = true;
            } else if ( $scope.loginDropDownStatus == true ) {
                dropDownService.hideLoginDropDown();
                $scope.loginDropDownStatus = false;
            }
        };

    })

        .controller("RegistrationDropDownController", function ($scope, dropDownService) {

        $scope.registrationDropDownStatus = dropDownService.getRegistrationDropDownStatus();

        $scope.$watch('registrationDropDownStatus', function(newValue, oldValue) {
            console.log("watcher is working");
            console.log("value is " + newValue + oldValue);

            console.log("new value is " + newValue);
            $scope.registrationDropDownStatus = newValue;
        });

        $scope.toggleDropDown = function () {

            if ( $scope.registrationDropDownStatus == false ) {
                dropDownService.showRegistrationDropDown();
                dropDownService.hideLoginDropDown();
                $scope.registrationDropDownStatus = true;
            } else if ( $scope.registrationDropDownStatus == true ) {
                dropDownService.hideRegistrationDropDown();
                $scope.registrationDropDownStatus = false;
            }
        };

        })

3 个答案:

答案 0 :(得分:1)

编辑:

这可能是最短的选择:

angular.module("ftApp", [])
    .controller("ctrl", function ($scope) {
    $scope.toggle = function(menu){
         $scope.active = $scope.active === menu ? null : menu;
    }
})

FIDDLE

一个控制器,没有服务。


上一个答案:

我认为你有相当多的代码来完成一些非常简单的事情。这是我的解决方案:

angular.module("ftApp", [])
    .service('dropDownService', function () {        
        this.active = null;
        this.toggle = function(menu){
            this.active = this.active === menu ? null : menu;
        }
})

    .controller("LoginDropDownController", function ($scope, dropDownService) {
    $scope.status = dropDownService;
    $scope.toggleDropDown = function () {
        dropDownService.toggle("login");
    };

})

    .controller("RegistrationDropDownController", function ($scope, dropDownService) {
    $scope.status = dropDownService;
    $scope.toggleDropDown = function () {
        dropDownService.toggle("reg");
    };

})

FIDDLE

只需使用一个控制器即可使其更短。你甚至不需要这项服务。

答案 1 :(得分:0)

你太复杂了。您需要保留的服务是指示哪个dorpdown应该处于活动状态的属性。

然后,您可以从控制器更改该属性的值,并检查视图中的值,以确定是否应显示或隐藏下拉列表。

这样的事情:

<!-- In the VIEW -->
<li ng-controller="XyzController">
    <a ng-click="toggleDropdown()">Xyz</a>
    <div ng-show="isActive()">Dropdown</div>
</li>

/* In the SERVICE */
.factory('DropdownService', function () {
    return {
        activeDropDown: null
    };
})

/* In the CONTROLLER */
controller("XyzDropdownController", function ($scope, DropdownService) {
    var dropdownName = 'xyz';
    var dds = DropdownService;
    $scope.isActive = function () {
        return dropdownName === dds.activeDropdown;
    };
    $scope.toggleDropdown = function () {
        dds.activeDropdown = (dds.activeDropdown === dropdownName) ?
                null :
                dropdownName;
    };
})

另请参阅此 short demo


<子> 根据你究竟在做什么,可能还有其他方法/可取的:
例如。你可以只使用控制器来控制所有下拉菜单 或者您可以使用同一控制器的两个实例来控制每个下拉列表。

答案 2 :(得分:-1)

查看我更新的fiddle。我简化了代码并删除了服务。因为您只使用了两个变量来控制可见性,所以您不需要服务,也不需要$watch。您需要在$rootScope中保留变量,否则由于隔离的范围,控制器中的更改对另一个控制器不可见。

angular.module("ftApp", [])
    .controller("LoginDropDownController", function ($scope, $rootScope) {
    $rootScope.loginDropDownStatus = false;
    $scope.toggleDropDown = function () {
        if ($rootScope.loginDropDownStatus == false) {
            $rootScope.registrationDropDownStatus = false;
            $rootScope.loginDropDownStatus = true;
        } else if ($rootScope.loginDropDownStatus == true) {
            $rootScope.loginDropDownStatus = false;
        }
    };
}).controller("RegistrationDropDownController", function ($scope, $rootScope) {
    $rootScope.registrationDropDownStatus = false;
    $scope.toggleDropDown = function () {

        if ($rootScope.registrationDropDownStatus === false) {
            $rootScope.loginDropDownStatus = false;
            $rootScope.registrationDropDownStatus = true;
        } else if ($scope.registrationDropDownStatus === true) {
            $rootScope.registrationDropDownStatus = false;
        }
    };

})

此代码可以进一步简化。我会把它留给你。