angularjs ng-if difference between value and function - angularjs

Is there any difference using
ng-if with a value or with a function ?
ng-if="myvalue"
ng-if="myfunc()"
UPDATE (for a better understanding why I'm asking for)
html
<div class="navbar navbar-default navbar-static-top" data-ng-controller="NavController as nav">
<div class="container">
<ul class="nav navbar-nav">
<a data-ui-sref="home" class="navbar-brand"><i class="logo"></i> Angular Express</a>
<li ui-sref-active="active"><a data-ui-sref="home">Home</a></li>
</ul>
<ul class="nav navbar-nav navbar-right" data-ng-if="!nav.isAuthenticated()">
<li><a data-ui-sref="session.login">Log in</a></li>
<li><a data-ui-sref="session.signup">Sign up</a></li>
</ul>
<ul class="nav navbar-nav navbar-right" data-ng-if="nav.isAuthenticated()">
<li><i class="fa fa-user"></i> <span ng-bind="nav.isAuthenticated().username"></span> Logout</li>
</ul>
</div>
</div>
js
function NavController($rootScope, UserStorage){
var nav = this;
nav.isAuthenticated = function() {
UserStorage.get();
};
}
function UserLoginController($rootScope,$state, Users, UserStorage) {
var user = this;
user.data = {};
user.save = function() {
Users.login(user.data).then(function(response) {
console.log(response.data);
UserStorage.set(response.data);
$state.go('home');
})
.catch(function(response) {
console.log(response);
user.errors = response.data;
});
};
}
If I use like this I've got a $digest() iterations reached
RE UPDATE
(for chandermani comment)
function UserStorage($sessionStorage) {
return {
set: function(data) {
$sessionStorage.user = angular.toJson(data);
},
get: function() {
return angular.fromJson($sessionStorage.user);
},
del: function() {
delete $sessionStorage.user;
}
};
}

For angular both are expression, that it evaluates in context of current scope. Angular does this on each digest cycle.
There are more ways to shoot in the foot if you are using the function way. myfunc could do
$scope.myfunc=function() {
//do some time consuming work
return data;
};
In such a case the binding evaluation on each digest cycle will make your binding and app slow.
So if you are using function based binding make sure that functions return fast by doing minimum processing.

Calling functions on ng-repeat directives can cause some performance issues, but if it's a one off evaluation then there isn't really a difference as far as I've noticed.
I always try to evaluate the property: ng-if="myValue" would evaluate the scope variable $scope.myValue

Related

I am using Angular 1 and I am trying to ng-hide my login button once a user is logged in?

I know I am suppose to do and ng-hide="something", but I don't where to go from there. Not sure if I have to also write another function in my logoutController or mainController.
<ul class="right hide-on-med-and-down">
<li><a ui-sref="login">Login</a></li>
<li><a ui-sref="logout" ng-click='logoutCtrl.logout()'>Logout</a></li>
</ul>
</div>
nav.html
function logoutController($state, AuthService) {
var vm = this
vm.logout = function () {
// call logout from service
AuthService.logout()
.then(function () {
$state.go('login')
})
}
}
app.js
It depend the way you're login works but you can do
<ul class="right hide-on-med-and-down">
<li><a ng-show="inNotLogged"ui-sref="login">Login</a></li>
<li><a ui-sref="logout" ng-click='logoutCtrl.logout()'>Logout</a></li>
</ul>
</div>
and in your app.js .run set $rootScope.isNotLogged = true;then in your login method:
$rootScope.isNotLogged = false;
$scope.isNotLogged = $rootScope.isNotLogged;
so in tour lgout you will set
$scope.isNotLogged = true;
$rootScope.isNotLogged = $scope.isNotLogged;

I keep on getting TypeError: v2.CurrentTaskForce is not a function

Left hand side of the page is displaying list of task force.
On click of the list item related data is to be displayed on right hand side.
When I click on the list item, first time it works fine. It displays the task force name as a header in right hand side panel. When I click on another list item it gives TypeError: v2.CurrentTaskForce is not a function
var VirtualDir = GetVirtualDirectory();
angular.module('MyApp',[])
.controller('TaskForceController', function ($scope, TaskForceService) { // inject taskforce service
$scope.TaskForceList = null;
//$scope.CurrentTaskForce = {}
TaskForceService.GetTaskForceList().then(function (d) {
$scope.TaskForceList = d.data;
}, function () {
alert('failed');
});
$scope.CurrentTaskForce = function (item) {
angular.forEach($scope.TaskForceList, function (value, index) {
value.IsActive = false ;
})
item.IsActive = true;
alert("s");
$scope.CurrentTaskForce = item;
}
})
.factory('TaskForceService', function ($http) { //here factory is created which is a populer way to create and configure services
var fac = {};
fac.GetTaskForceList = function () {
return $http.get(VirtualDir + '/TaskForce/GetMyTaskForce/');
}
return fac;
});
<div class="container-fluid" ng-controller="TaskForceController as tf">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar" >
<%-- <li class="active">Overview <span class="sr-only">(current)</span></li>--%>
<li ng-repeat="item in TaskForceList" ng-class="{active: item.IsActive == true}" ng-click="CurrentTaskForce(item)" ><a href="#" >{{item.TaskForce}}</a></li>
</ul>
</div>
<div class="col-sm-9 co-md-9" style="left:20%">
<div class="panel panel-default" ">
<div class="panel-heading">
<p class="panel-title">{{CurrentTaskForce.TaskForce}}</p>
<!--ng-repeat="curritem in CurrentTaskForce"-->
</div>
</div>
</div>
</div>
</div>
While copying item to CurrentTask force instead of
$scope.CurrentTaskForce = item;
I used
angular.copy(item, $scope.CurrentTaskForce);
It is happening because CurrentTaskForce is defined as a function and a variable in same controller. Please use a different name for either.

angularJS parent scope not updating from directive

So here is my issue, I can't get my $scope.documents to update from my directive.$scope.parentUpdate({ documents: $scope.docType}) does not seem to execute at all an so my documents never updates. $scope.docType= resultgets all the data I need but it just does not push it back to the parent controller.
app.controller('docGridController',['$scope','getSideNav', 'getDocuments',
function($scope, getSideNav, getDocuments){
getSideNav().then(function(result){$scope.SideNav = result;
},
function(error){$scope.error = result;});
$scope.slideToggle = true;
$scope.documents=[];
$scope.update = function(k){
$scope.documents = k;
consle.log($scope.documents);
}}]);
app.directive('foSidenav',['getDocuments',function(getDocuments){
return{
replace: true,
scope: {
info:'=',
docType:'=',
parentUpdate:'&'
},
templateUrl:function(element,attr){
return attr.url;
},
controller: ['$scope','$element', '$attrs' ,'getDocuments',
function($scope,$element, $attrs, getDocuments){
$scope.selectDocType = function(id)
{
getDocuments(id).then(function(result){$scope.docType= result;
console.log($scope.docType);
alert('Printed results');
$scope.parentUpdate({ documents: $scope.docType});
},
function(error){$scope.error = result;});
};
}]
};
}]);
Here is the tag I am using in my template
<ul class="side-nav">
<li class="mainCat" ng-repeat=" item in info">
<a href="#" id="CatHeader" ng-click="slideToggle =! slideToggle">
<i class="{{item.displayIcon}} left-bar"></i>
<span ng-bind-html="item.label | html"></span>
</a>
<ul class="subCat slide-toggle" ng-show="slideToggle">
<li ng-repeat="subItem in item.docTypes">
<a href="#" ng-click="selectDocType(subItem.id)" >
<i class="fi-folder"></i>
<span ng-bind-html="subItem.Name | html"></span>
</a>
</li>
</ul>
</li>
and here is the directive call
<fo-sidenav url="{!URLFOR($Resource.FOPS_Resource, 'components/sidenav.html')}" info='SideNav' docType='documents' parentUpdate="update(documents)"></fo-sidenav>
Any ideas?? these scope are really throwing me off
I think the issue is with how you are using the variables from your isolated scope in the html. Now you are using them like below:
<fo-sidenav url="{!URLFOR($Resource.FOPS_Resource, 'components/sidenav.html')}"info='SideNav' docType='documents' parentUpdate="update(documents)"></fo-sidenav>
Try like the following:
<fo-sidenav url="{!URLFOR($Resource.FOPS_Resource, 'components/sidenav.html')}" info='SideNav' doc-type='documents' parent-update="update(documents)"></fo-sidenav>
For more information about read Matching Directives and Normalization sections here

AngularJS - Change value from one view to antoher

I have the following layout:
<nav ng-include="'views/nav.html'"></nav>
<div class="container-fluid">
<div ng-view></div>
</div>
Inside nav.html I want to display a dropdown link, once someone has entered a page, and has access. This page is rendered in the ng-view div
Right now I am using a service to update the shared value from one controller to the nav controller. However, the value is never updated in the nav controller. It is set in the service, but not updated.
<nav class="navbar navbar-inverse" role="navigation" ng-controller="LoginController as login">
<div class="container-fluid">
<ul class="nav navbar-nav">
<li>Show option '{{login.showOption}}' <span class="glyphicon glyphicon-info-sign"></span></li>
<li ng-if="login.showOption" dropdown>
<a href class="dropdown-toggle" dropdown-toggle>
Options <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a ng-href>1</a></li>
<li><a ng-href>2</a></li>
</ul>
</li>
</ul>
</div>
</nav>
LoginController.js
var LoginController = function (Option) {
var model = this;
model.showOption = Option.getValue();
module.controller("LoginController", ['Option', LoginController]);
}(angular.module("myApp")));
Option.js
'use strict';
(function (module) {
var option = function () {
var value = false;
return {
getValue: function() {
return value;
},
setValue: function(newVal) {
value = newVal;
}
};
};
module.service("Option", option);
}(angular.module("civApp")));
I am updating the Option.getValue() from another controller in another view, however the nav isn't getting updated.
GameController.js
var GameController = function (Option) {
Option.setValue(true);
module.controller("GameController", ['Option', GameController]);
}(angular.module("myApp")));
When I call this code, the view in the nav.html is not updated. I can see that the Option service is called, but I was hoping the value would have been updated in the view also.
GameController
LoginController
Nav.html
I can clearly see in GameController#watch that the Option.value:show is correctly set to true
That can be sorted using by angular dot rule
just update your code to :
Option Service
(function (module) {
var option = function () {
//value.show instead value
var value = {
show: false
};
return {
value: value
};
};
module.service("Option", option);
}(angular.module("civApp")));
and after that in your controllers
Login
var LoginController = function (Option) {
var model = this;
model.showOption = Option.value;
module.controller("LoginController", ['Option', LoginController]);
}(angular.module("myApp")));
GameController
var GameController = function (Option) {
Option.value = {
show: true
};
module.controller("GameController", ['Option', GameController]);
}(angular.module("myApp")));
and finally in your view
<li>Show option '{{login.showOption.show}}' <span class="glyphicon glyphicon-info-sign"></span>

Can't get ng-hide & ng-show to work with tokens

My problem is similar to this : ng-show and ng-hide with jwt
Although i modified as instructed by user3735441, i still can't make them work properly:
Service :
'use strict';
/**
* #ngdoc service
* #name ToDoManagerApp.authToken
* #description
* # authToken
* Factory in the ToDoManagerApp.
*/
angular.module('ToDoManagerApp').factory('authToken', function($window) {
var storage = $window.localStorage;
var cachedToken;
var userToken = 'userToken';
var isAuthenticated = false;
// Public API here
var authToken = {
setToken: function(token) {
cachedToken = token;
storage.setItem(userToken, token);
isAuthenticated = true;
},
getToken: function() {
if(!cachedToken)
cachedToken = storage.getItem(userToken);
return cachedToken;
},
isAuthenticated: function() {
return !!authToken.getToken();
},
removeToken: function() {
cachedToken = null;
storage.removeItem(userToken);
isAuthenticated = false;
}
};
return authToken;
});
Controller :
angular.module('ToDoManagerApp').controller('HeaderCtrl', function($scope, authToken) {
$scope.isAuthenticated = authToken.isAuthenticated;
});
HTML :
<div ng-controller = "HeaderCtrl" class="header">
<div class="navbar navbar-default" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#js-navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#/">ToDoManager</a>
</div>
<div class="collapse navbar-collapse" id="js-navbar-collapse">
<ul class="nav navbar-nav">
<li ui-sref-active="active">
<a ui-sref="main">Home</a>
</li>
<li ng-hide="isAuthenticated()" ui-sref-active="active">
<a ui-sref="register">Register</a>
</li>
<li ng-show="isAuthenticated()" ui-sref-active="active">
<a ui-sref="logout">Logout</a>
</li>
</ul>
</div>
</div>
</div>
</div>
What i'm trying to do is to :
1 - show register, hide logout when no token is set (not authenticated) OR
2 - show logout, hide register when a token is set (authenticated)
For now i'm stuck with the first state, authenticated or not i can't see the logout button.
You are accessing the $scope model with ng-hide and ng-show.
In your Service, you are setting isAuthenticated to false, and never setting it to True. So your app is stuck in your first state, where the isAuthenticated is false.
I completly forgot to add 'res' in my register controller, that's why it wasn't updated :
$http.post(url, user)
.success(function(res) {
alert('success', 'OK!', 'You are now registered');
authToken.setToken(res.token);
})
This is happening because your variable in your controller is not updating when it changes in your factory. To work around this, I usually use $broadcast. So in your factory you would have some function like this...
var broadcastValue = function() {
$rootScope.$broadcast('IsAuthenticated');
}
You would then call this function at whatever point you wanted the receivers to check the variable.
Then in your controller you would have something like this to receive the broadcast
$scope.$on('IsAuthenticated', function() {
$scope.isAuthenticated = authToken.isAuthenticated;
});
This will make sure your controller sees when the value changes.
Also see this post.
$on and $broadcast in angular

Resources