简体   繁体   中英

ng-show doesn't work with $scope

I'm new to angular and can't understand why the ng-show in the below code isn't working. The isLoggedIn is a variable in $scope.

<html ng-app"XYZ"
<body>
    <nav id="myNav" ng-show = "isLoggedIn" ng-controller="NavBarController as navCtrl">
        <div class="nav-wrapper">
            <a href="#!" class="brand-logo">Logo</a>
            <a href="#" data-activates="mobile-demo" class="button-collapse">
                <i class="material-icons">menu</i>
            </a>
            <ul class="side-nav" id="mobile-demo">
                <li>
                    <a href="sass.html">Sass</a>
                </li>
                <li>
                    <a href="badges.html">Components</a>
                </li>
                <li>
                    <a href="collapsible.html">Javascript</a>
                </li>
                <li>
                    <a href="mobile.html">Mobile</a>
                </li>
            </ul>
        </div>
    </nav>
    <div ng-view>

    </div>...</body></html>

Another template:

 <button class = "btn" ng-click = "loginCtrl.doLogin()">LOGIN</button>

The loginCtrl:

angular.module('XYZ')
.controller('LoginController', ['NetworkService',
    '$routeParams',
    '$location',
    '$scope',
    '$timeout',
    function(NetworkService, $routeParams, $location,$scope,$timeout) {
        var self = this;
        $scope.isLoggedIn = false;
        // $scope.$apply();
        self.doLogin = function(){
            $scope.isLoggedIn = true;
        }
    }
]);

I tried calling $scope.$apply() after I changed the isLoggedIn variable which results in an exception '$apply already in progress'. I also tried encapsulating the doLogin's inner code in a $timeout() which also failed.

EDIT:

config:

angular.module('XYZ')
.config(function($routeProvider) {
    console.log("Configuring routes");
    $routeProvider.when('/login', {
            templateUrl: "./templates/login.html",
            controller: "LoginController",
            controllerAs: "loginCtrl"
        })
    });

The problem you are facing is that you are instantiating a new module, but it requires a second argument (the dependencies).

Since you aren't providing any dependencies, you actually do need to pass an empty array [] as a second parameter. And seeing you are using $routeProvider in your .config() you should have to include either the dependency provided by AngularJS or some other kind of "routing' dependency (such as ui-router )

So your code would have to look like this:

Config


angular.module('XYZ', ['ngRoute'])
.config(function($routeProvider) {
    console.log("Configuring routes");
    $routeProvider.when('/login', {
            templateUrl: "./templates/login.html",
            controller: "LoginController",
            controllerAs: "loginCtrl"
        })
    });

LoginController


angular.module('XYZ', ['ngRoute'])
.controller('LoginController', ['NetworkService',
    '$routeParams',
    '$location',
    '$scope',
    '$timeout',
    function(NetworkService, $routeParams, $location,$scope,$timeout) {
        var self = this;
        $scope.isLoggedIn = false;
        // $scope.$apply();
        self.doLogin = function(){
            $scope.isLoggedIn = true;
        }
    }
]);

it's also a bad practice to reinstantiate your module each time, so assign it to a variable ( var myApp = angular.module('XYZ', ['ngRoute']); ) and use that variable to instantiate controllers, services, factories, etc.

Here's a fiddle to show the functionality (incl. the URL to angular-route.js, which you will need if you're using routing). It's not an exact replica of your code because JSFiddle doesn't handle routing all too well.

your controller is called LoginController therefore ng-controller=LoginController, the controller also needs to be called in the parent tag to any other directives....see below fix.

<body ng-controller="LoginController">
<nav id="myNav" ng-show = "isLoggedIn" >
    <div class="nav-wrapper">
        <a href="#!" class="brand-logo">Logo</a>
        <a href="#" data-activates="mobile-demo" class="button-collapse">
            <i class="material-icons">menu</i>
        </a>
        <ul class="side-nav" id="mobile-demo">
            <li>
                <a href="sass.html">Sass</a>
            </li>
            <li>
                <a href="badges.html">Components</a>
            </li>
            <li>
                <a href="collapsible.html">Javascript</a>
            </li>
            <li>
                <a href="mobile.html">Mobile</a>
            </li>
        </ul>
    </div>
</nav>
<div ng-view>

</div>...</body></html>
angular.module('XYZ')
.controller('LoginController', ['$routeParams',
    '$location',
    '$scope',
    '$timeout',
    function($scope) {

    $scope.isLoggedIn = false;

    $scope.doLogin = function(){
        $scope.isLoggedIn = true;
    };
}
]);

You need not a create a service for simply setting $scope of object to true or false, you can handle it using controller itself. And in HTML, do the following change for ng-click

 <button class = "btn" ng-click = "doLogin()">LOGIN</button>

This should work.

I solved it. The problem was that the element I wanted to hide (or show) was out of LoginController's scope. Since $scope.isLoggedIn is being changed in the controller's scope, $scope is not aware of the HTML it needs to change which is not in the same scope. Putting 'isLoggedIn' in $rootScope works. Thanks to @Jorrex for helping and giving me the solution and everyone who tried to help me.

//solution
app.controller('LoginController', ['NetworkService', '$routeParams',
'$location',
'$scope',
'$timeout',
'$rootScope',
function(NetworkService, $routeParams, $location,$scope,$timeout,$rootScope) {

        $scope.doLogin = function(){
            $rootScope.isLoggedIn = true;
        }
    }
]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM