ng-include causes the controller block to re render

angularjs

Solution

I believe your problem is a result of the way prototypal inheritance works. ng-include creates its own child scope. Assigning a primitive value in a child scope creates a new property on that scope that shadows/hides the parent property.

I'm guessing that in login_form.html you do something like the following when a user logs in:

<a ng-click="isLoggedIn=true">login</a>

Before isLoggedIn is set to true, this is what your scopes look like:

After isLoggedIn is set to true, this is what your scopes look like:

Hopefully the pictures make it clear why this is causing you problems.

For more information about why prototypal inheritance works this way with primitives, please see What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

As the above link explains, you have three solutions:

- define an object in the parent for your model, then reference a property of that object in the child: parentObj.isLoggedIn

- use $parent.isLoggedIn in login_form.html -- this will then reference the primitive in the $parent scope, rather than create a new one. E.g., `<a ng-click="$parent.isLoggedIn=true">login</a>`

- define a function on the parent scope, and call it from the child -- e.g., setIsLoggedIn(). This will ensure the parent scope property is being set, not a child scope property.

Update: in reviewing your HTML, you may actually have two levels of child scopes, since ng-switch and ng-include each create their own scopes. So, the pictures would need a grandchild scope, but the three solutions are the same... except for #2, where you would need to use $parent.$parent.isLoggedIn -- ugly. So I suggest option 1 or 3.

Update2: @murtaza52 added some code to the question... Remove `ng-init="isLoggedIn = false"` from your controller (your service is managing the login state via its `isUserLoggedIn` variable) and switch on loginStatus() in your controller: `<div ng-switch on="loginStatus()">`.

Here is a working fiddle.

Problem

I am trying to use ng-switch with ng-include below. The problem is with ng-init and the whole controller block getting re-rendered on any ng-includes change. In the login_form.html, when a user logins, I set the isLoggedIn = true, in the LoginCtrl. However this causes the re-rendering of the full html below, which causes the ng-init again. How do I avoid this cycle? ``` <div ng-controller="LoginCtrl" ng-init="isLoggedIn = false" class="span4 pull-right"> <div ng-switch on="isLoggedIn"> <div ng-switch-when="false" ng-include src="'login_form.html'"></div> <div ng-switch-when="true" ng-include src="'profile_links.html'"></div> </div> </div> ``` Below is the HTML for the login form - ``` <form class="form-inline"> <input type="text" placeholder="Email" ng-model="userEmail" class="input-small"/> <input type="password" placeholder="Password" ng-model="userPassword" class="input-small"/> <button type="submit" ng-click="login(userEmail, userPassword)" class="btn">Sign In</button> </form> ``` Below is the controller - ``` angularApp.controller('LoginCtrl', function($scope, currentUser){ $scope.loginStatus = function(){ return currentUser.isLoggedIn(); }; /* $scope.$on('login', function(event, args) { $scope.userName = args.name; }); $scope.$on('logout', function(event, args) { $scope.isLoggedIn = false; });*/ $scope.login = function(email, password){ currentUser.login(email, password); }; $scope.logout = function(){ currentUser.logout(); }; }); ``` Blow is the service - ``` angularApp.factory('currentUser', function($rootScope) { // Service logic // ... // var allUsers = {"rob@gmail.com": {name: "Robert Patterson", role: "Admin", email: "rob@gmail.com", password: "rob"}, "steve@gmail.com":{name: "Steve Sheldon", role: "User", email: "steve@gmail.com", password: "steve"}} var isUserLoggedIn = false; // Public API here return { login: function(email, password){ var user = allUsers[email]; var storedPass = user.password; if(storedPass === password){ isUserLoggedIn = true; return true; } else { return false; } }, logout: function(){ $rootScope.$broadcast('logout'); isUserLoggedIn = false; }, isLoggedIn: function(){ return isUserLoggedIn; } }; }); ```

Original source

Related problems