Reputation: 760
I have two ng-if
s defined in the same template that call functions of the same controller:
<div ng-controller="UserController">
<!-- WORKS :) -->
<p>{{ user.name }}</p>
<!--WORKS :)-->
<div ng-if="showThingOne()">
<h2>Thing One</h2>
</div>
<!--DOESN'T WORK :( ; TypeError: Cannot read property 'role' of undefined -->
<div ng-if="showThingTwo(user)">
<h2>Thing Two</h2>
</div>
</div>
angular.module('MyApp')
.controller('UserController', ['$rootScope', '$scope', 'User', function ($rootScope, $scope, User) {
var getCurrentUser = function () {
User.current(function (user) {
$scope.user = user;
$rootScope.currentUser = user;
});
};
getCurrentUser();
$scope.showThingOne = function () {
return $scope.user.role === 'Thing One Seer';
};
$scope.showThingTwo = function (user) {
return user.role === 'Thing Two Seer';
};
}]);
The second conforms with a bunch of things I've read about unit testing, while the first is always marked "Don't do it this way", so I'd like to write my functions the second way. Also, I'd like to understand why the first works and the second doesn't; I'm guessing it has something to do with how the DOM is compiled during $digest, but that's just a random guess with no real support in the Angular source or docs.
Upvotes: 3
Views: 182
Reputation: 6903
The User.current is an async function so the result get ready after the dom compiled.
showThingOne has no argument to be evaluated at compile time.
Solution
Add
$scope.user = {};
as the first line of user controller.
angular.module('MyApp')
.controller('UserController', ['$rootScope', '$scope', 'User', function ($rootScope, $scope, User) {
$scope.user = {};
var getCurrentUser = function () {
User.current(function (user) {
$scope.user = user;
$rootScope.currentUser = user;
});
};
getCurrentUser();
$scope.showThingOne = function () {
return $scope.user.role === 'Thing One Seer';
};
$scope.showThingTwo = function (user) {
return user.role === 'Thing Two Seer';
};
}]);
Upvotes: 1
Reputation: 67316
This doesn't work because user
is never being used:
$scope.showThingTwo = function (user) {
return $scope.user.role === 'Thing Two Seer';
};
Only $scope.user.role
is being used (but not the user
parameter) and it is still set to the 'Thing One Seer'
value.
If you use it like this it might work this way you are intenting:
$scope.showThingTwo = function (user) {
if (user) {
return user.role === 'Thing Two Seer';
}
return false;
};
Upvotes: 0