Angularjs - hide div with "if" and "else" - javascript

I would only like to show a div when user is logged in and on their profile but disabled when logged off and on another users profile.
I attempted to do this below but was unsuccessful. I would like to know what is the best possible way of going about this?
Service.js
(function () {
'use strict';
angular
.module('app.authentication.services')
.factory('Authentication', Authentication);
Authentication.$inject = ['$cookies', '$http'];
function Authentication($cookies, $http) {
var Authentication = {
getAuthenticatedAccount: getAuthenticatedAccount,
isAuthenticated: isAuthenticated
};
return Authentication;
function getAuthenticatedAccount() {
if(!$cookies.authenticatedAccount) {
return;
}
return JSON.parse($cookies.authenticatedAccount);
}
function isAuthenticated() {
return !!$cookies.authenticatedAccount;
}
})();
Controller.js
(function () {
'use strict';
angular
.module('app.profiles.controllers')
.controller('ProfileController', ProfileController);
ProfileController.$inject = ['$location', '$routeParams', 'Posts', 'Profile', 'Snackbar'];
function ProfileController($location, $routeParams, Posts, Profile, Authentication, Snackbar) {
var vm = this;
activate();
function activate() {
var authenticatedAccount = Authentication.getAuthenticatedAccount();
var username = $routeParams.username.substr(1);
// This will show Cog settings button
// when user is logged in and on their profile,
// but hidden when logged off and also when on
// another users profile
if (!authenticatedAccount) {
vm.profileCog = false;
// console.log('User not logged in');
}
else {
if(authenticatedAccount.username !== username) {
vm.profileCog = false;
// console.log('Not logged in user');
}
else {
vm.profileCog = true;
//console.log('logged in user');
}
}
}
})();
profile.html
<div ng-controller="ProfileCogController">
<div ng-show="!profileCog"></div>
</div>

According to your comment that getAuthenticatedAccount is always asynchronous:
This means you'll need to either A) explicitly watch it, or B) evaluate it once it completes. Something like this:
function activate() {
Authentication.getAuthenticatedAccount().then(function(account) {
var username = $routeParams.username.substr(1);
if(!account || account.username !== username) {
vm.profileCog = false;
}
});
// rest of code omitted
You'll need to make sure that Authentication.getAuthenticatedAccount returns a promise for this to work (by default, async calls using AngularJS internal libraries should always return a promise, aka, something that is thenable).

Solved:
controller.js
(function () {
'use strict';
angular
.module('resonanceinn.profiles.controllers')
.controller('ProfileCogController', ProfileCogController);
ProfileCogController.$inject = ['Authentication', '$routeParams', 'Profile'];
function ProfileCogController(Authentication, $routeParams, Profile) {
var vm = this;
vm.profileCog = false;
activate();
function activate() {
var authenticatedAccount = Authentication.getAuthenticatedAccount();
var username = $routeParams.username.substr(1);
if (!authenticatedAccount) {
vm.profileCog = false;
// console.log('User not logged in');
}
else {
if(authenticatedAccount.username !== username) {
vm.profileCog = false;
// console.log('Not logged in user');
} else {
vm.profileCog = true;
// console.log('logged in user');
}
}
}
}
})();
profile.html
<div ng-controller="ProfileCogController">
<div ng-show="vm.profileCog"></div>
</div>

you need to specify the controller and app name in your html file:
1) specify the controller and app name in any parent tag of current div tag if any
2) otherwise, specify the same with in the same div tag
Like:
angular.module('showApp', [])
.controller('mainController', function($scope) {
$scope.isvisible=false;
$scope.showDiv=function()
{
if(!$scope.isvisible)
$scope.isvisible=true
else
$scope.isvisible=false
}
});
<!doctype html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Example</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular-animate.js"></script>
</head>
<body ng-app="showApp" ng-controller="mainController">
Show me: <input type="checkbox" ng-click="showDiv()" ><br/>
<div ng-show="isvisible">I show up when your checkbox is checked.
</div>
</body>
</html>
Thanks,

Related

AngularJS: basic error-handling

I would like to reflect post request status by showing/hiding success/error html element with the error description. I have following controller with use of $http service:
$ctrl.addCorporateTransport = function() {
var postStatusBar = angular.element('postStatusBar');
$http.post('/post_corporate_transport', $ctrl.corporateTransport)
.success(function () {
// throw success alert
})
.error(function (error) {
// throw error alert
});
};
I'm looking for having possibility to throw <div class="alert"><p>my error here</p> if I hit error callback.
I tried this:
var statusBar = angular.element('postStatusBar');
//...
.success(function () {
statusBar.setClass("alert-success")
})
.error(function (error) {
statusBar.setClass("alert-danger");
statusBar.setParameter("text", error);
});
But it doesn't work obviously and looks like anti-pattern. What is the best solution for doing the thing?
If the alert component is outside controller scope than you need make the alert a directive and use broadcast to notify and update properties like visibility.
else you can bind properties from controller like:
<div ng-controller="AwesomeController as AwesomeCtrl">
<div class="alert" ng-show="AwesomeCtrl.show.error">....
<div class="alert" ng-show="AwesomeCtrl.show.success">....
<div class="alert" ng-class="{ 'succes' : AwesomeCtrl.show.success }">....
enter code here
angular
.module('app')
.controller('AwesomeController', controller);
controller.$inject = ['$http'];
function controller($http) {
var vm = this;
vm.corporateTransport = {};
vm.show = {
error = false;
success = false;
}
vm.oneCoolMethod = addCorporateTransport;
// test
addCorporateTransport();
function addCorporateTransport() {
$http.post('/post_corporate_transport', vm.corporateTransport)
.success(onTransportSuccess)
.error(onTransportError);
};
function onTransportSuccess(result) {
toggleAlert('success');
}
function onTransportError(result) {
toggleAlert('error');
}
function toggleAlert(level) {
angular.forEach(vm.show, function(value, key) {
vm.show[key] = false;
});
vm.show[level] = true;
}
at the first you must using $scope.statusBar
and also addClass except setClass

Jhipster generated app, default AngularJS register form

I created an app using JHipster and try to edit the `register.html'. The code where I need help is shows below:
<div class="alert alert-success" ng-show="vm.success" data translate="register.messages.success">
<strong>Registration saved!</strong> Please check your email for confirmation.
</div>
<div class="alert alert-danger" ng-show="vm.error" data-translate="register.messages.error.fail">
<strong>Registration failed!</strong> Please try again later.
</div>
I omitted the rest of the code as they are equal to these two, only with different messages and ng-models . & the register.controller.js :
(function() {
'use strict';
angular
.module('MyApp')
.controller('RegisterController', RegisterController);
RegisterController.$inject = ['$translate', '$timeout', 'Auth', 'LoginService'];
function RegisterController ($translate, $timeout, Auth, LoginService) {
var vm = this;
vm.doNotMatch = null;
vm.error = null;
vm.errorUserExists = null;
vm.login = LoginService.open;
vm.register = register;
vm.registerAccount = {};
vm.success = null;
$timeout(function (){angular.element('#login').focus();});
function register () {
if (vm.registerAccount.password !== vm.confirmPassword) {
vm.doNotMatch = 'ERROR';
} else {
vm.registerAccount.langKey = $translate.use();
vm.doNotMatch = null;
vm.error = null;
vm.errorUserExists = null;
vm.errorEmailExists = null;
Auth.createAccount(vm.registerAccount).then(function () {
vm.success = 'OK';
}).catch(function (response) {
vm.success = null;
if (response.status === 400 && response.data === 'login already in use') {
vm.errorUserExists = 'ERROR';
} else if (response.status === 400 && response.data === 'e-mail address already in use') {
vm.errorEmailExists = 'ERROR';
} else {
vm.error = 'ERROR';
}
});
}
}
}
})();
My question is by default the error handling messages must be hidden, and once the form is valuated, they should be shown based on the condition. But I cannot figure out how to make this work...
Below is the default register.html page:
The generated register.html does not show those messages by default. It looks like you are loading just the HTML file into the browser, but you need to run the app and load the index.html from there to run the Angular code.
Run ./mvnw or ./gradlew and access the frontend at http://localhost:8080
You can also run gulp which will serve your frontend at http://localhost:9000 with live-reloading when you make changes. More info can be found in the Using JHipster in development documentation
The register page looks like the following image when ran correctly:

AngularJS binding only updating after change

Hi I have created a factory to get the current amount of users online from my Firebase database.
When I first load the page it works great and displays all the current users but then if I go to another page and come back it will display as 0 until a new user connects or disconnects or if I refresh.
I followed this guide:
http://www.ng-newsletter.com/advent2013/#!/day/9
App.js
angular.module('myApp', ['ngRoute', 'firebase', 'ui.bootstrap'])
.factory('PresenceService', ['$rootScope',
function($rootScope) {
var onlineUsers = 0;
// Create our references
var listRef = new Firebase('https://my-db.firebaseio.com/presence/');
// This creates a unique reference for each user
var onlineUserRef = listRef.push();
var presenceRef = new Firebase('https://my-db.firebaseio.com/.info/connected');
// Add ourselves to presence list when online.
presenceRef.on('value', function(snap) {
if (snap.val()) {
onlineUserRef.set(true);
// Remove ourselves when we disconnect.
onlineUserRef.onDisconnect().remove();
}
});
// Get the user count and notify the application
listRef.on('value', function(snap) {
onlineUsers = snap.numChildren();
$rootScope.$broadcast('onOnlineUser');
});
var getOnlineUserCount = function() {
return onlineUsers;
}
return {
getOnlineUserCount: getOnlineUserCount
}
}
]);
mainController.js
angular.module('myApp')
.controller('mainController', function($scope, authService, PresenceService, $http, $routeParams, $firebaseObject, $firebaseAuth, $location) {
$scope.totalViewers = 0;
$scope.$on('onOnlineUser', function() {
$scope.$apply(function() {
$scope.totalViewers = PresenceService.getOnlineUserCount();
});
});
// login section and auth
var ref = new Firebase("https://my-db.firebaseio.com");
$scope.authObj = $firebaseAuth(ref);
var authData = $scope.authObj.$getAuth();
if (authData) {
console.log("Logged in as:", authData.uid);
$location.path( "/user/"+authData.uid );
} else {
console.log("Logged out");
$location.path( "/" );
}
// user ref
var userRef = new Firebase("https://my-db.firebaseio.com/users/"+ authData.uid);
var syncObject = $firebaseObject(userRef);
syncObject.$bindTo($scope, "data");
});
main.html
{{totalViewers}}
Inside your controller, change yr first line as below.
//$scope.totalViewers = 0;
$scope.totalViewers = PresenceService.getOnlineUserCount();
Because each time you leave the page, its controller gets flushed and next time its getting value "zero". So, correctly you should read $scope.totalViewers from your service.

How to inject my service into my controller angular js

I am relatively new to angular JS and I have an issue with angularJS 1.3.0 beta build
I am trying to insert my service (a standalone module) to a controller.
This is my app Code
'use strict';
angular.module('lifecareApp', [
'lifecareApp.validationServices'
, 'lifecareApp.loginController'
, 'lifecareApp.signupController'
]).
config(function ($routeProvider, $locationProvider) {
$routeProvider.
when('/account/login', {
controller: 'loginController'
}).
when('/account/signup', {
controller: 'signupController'
})
$locationProvider.html5Mode(true);
});
This is my service code
'use strict';
angular.module('lifecareApp.validationServices', []).
factory('validationServices', function () {
return {
validateRequiredField: function (value, requiredMessage) {
if (value){
return false; //returns false
}else{
if (requiredMessage){
return requiredMessage;
}else{
return "Required";
}
}
},
validateEmail: function (value, required, requiredMessage, invalidEmailMessage){
//validate if its required first
if (required){
if (value){
//validate the email next
var checkEmailRegex = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (checkEmailRegex.test(value)){
return false;
}else{
if (invalidEmailMessage){
return false;
}else{
return "Invalid Email";
}
}
}else{
if (requiredMessage){
return requiredMessage;
}else{
return "Required";
}
}
}
}
};
});
This is my controller code
'use strict';
/* Controllers */
angular.module('lifecareApp.loginController', []).
controller('loginController', ['$scope', 'validationServices' function ($scope, validationServices) {
$scope.emailError = false;
$scope.passwordError = false;
$scope.overallError = false;
$scope.login = function(){
var email = $scope.tbEmail;
var password = $scope.tbPassword;
var passwordValidation = validationServices.validateRequiredField(password);
var emailValidation = validationServices.validateEmail(email, true);
if (emailValidation){
$scope.emailError = true;
$scope.valEmail = emailValidation;
}else{
$scope.valEmail = "";
$scope.emailError = false;
}
if (passwordValidation){
$scope.passwordError = true;
$scope.valPassword = passwordValidation;
}else{
$scope.valPassword = "";
$scope.passwordError = false;
}
if (passwordValidation || emailValidation){
$scope.overallError = true;
$scope.valError = "Login Error!";
return;
}else{
$scope.overallError = true;
$scope.valError = "";
}
};
}]);
And I keep getting this error.
Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.3.0-beta.5/$injector/modulerr?p0=lifecareApp&…ngularjs.org%2F1.3.0-beta.5%2F%24injector%2Funpr%3Fp0%3D%2524routeProvider......5)
Please help! =(
I also found out that angular 1.0.7 does not have this error whereas the lastest angular 1.2.16 and 1.3.0 has this error.
In your main module you need to include ngRoute dependency with the new version of angularjs
angular.module('lifecareApp',['ngRoute',....
Also remember to include the route script file
<script src="angular-route.js">

angular: pass data when doing a $location.path()

I have two views right now.
login
main
Right now I login and change my path to /main which works fine. When I am not logged in, and try to visit /main my web service returns "Access denied for user anonymous" which I then forward them to / which is my login view. How can I pass something so my LoginController knows they were forwarded from /main to alert them to login first?
LoginController.js
VforumJS.controller('LoginController', function($scope, $location, $routeParams, LoginModel)
{
$scope.email = "";
$scope.password = "";
$scope.fetching = false;
$scope.error = null;
$scope.login = function()
{
$scope.error = null;
$scope.fetching = true;
LoginModel.login($scope.email, $scope.password);
}
$scope.$on('LoginComplete', function(event, args)
{
log('login complete: ' + args.result);
$scope.fetching = false;
if (args.result == "success")
{
$location.path('/main');
}
else
{
$scope.error = args.result;
}
});
});
MainController.js
VforumJS.controller('MainController', function($scope, $location, $routeParams, MainModel)
{
$scope.currentTitle = '-1';
$scope.presentationData = MainModel.getPresentations();
$scope.$on('PresentationsLoaded', function(event, args)
{
log(args.result);
if (args.result != "Access denied for user anonymous")
{
//-- Parse preso data
$scope.presentationData = args.result;
}
else
{
//-- Need to login first, route them back to login screen
$location.path("/");
}
});
});
You can use $location.search() in your MainController to pass query string to the LoginController.
Inside you MainController:
if (args.result != "Access denied for user anonymous")
{
//-- Parse preso data
$scope.presentationData = args.result;
}
else
{
//-- Need to login first, route them back to login screen
$location.search({ redirectFrom: $location.path() });
$location.path("/");
}
And then in your LoginController, shortened for brevity:
VforumJS.controller('LoginController', function($scope, $location, $routeParams, LoginModel)
{
var queryString = $location.search();
$scope.$on('LoginComplete', function(event, args)
{
log('login complete: ' + args.result);
$scope.fetching = false;
if (args.result == "success")
{
if (queryString && queryString.redirectFrom) {
$location.path(queryString.redirectFrom);
} else {
$location.path('/somedefaultlocation');
}
}
else
{
$scope.error = args.result;
}
});
});
Alternatively you can use a shared service, maybe even your LoginModel to set a parameter from MainController to indicate the redirect came from it.
Update
Even better still, use $httpProvider.interceptors to register a response interceptor, and then use the same $location.search() technique described above to redirect to the login screen on authentication failure. This method is ideal as your controllers are then clean of authentication logic.
$location broadcasts $locationChangeStart and $locationChangeSuccess events, and the third param of each is oldUrl.
One solution would be to have a service that subscribes to $locationChangeStart in order to save the current and old urls.
When you hit /, your LoginController can check your service to see if the oldUrl is /main, and then act accordingly.

Categories

Resources