Using scope from route config within html - javascript

As a beginner with AngularJs I am looking into creating a single page application and I am having trouble converting some early code into more professional code. In doing this conversion I moved all my 'page' html into their own .html files. I am using ng-view to then display the proper html page inside of my ng-view div tag. Although after moving all the code something is now wrong with calling my methods. Specifically I think my error is within the app.config for route or within my .html files content for calling this information. If I remove the ng-controller div from my .html how do I still use the default controller set from app.config?
Here is my app.route setup:
app.config(['$routeProvider',
function config($routeProvider) {
$routeProvider
// route for the home page
.when('/', {
templateUrl: 'pages/home.html',
controller: 'mainController'
})
// route for the about page
.when('/about', {
templateUrl: 'pages/about.html',
controller: 'aboutController'
})
// route for the contact page
.when('/contact', {
templateUrl: 'pages/contact.html',
controller: 'contactController'
});
}]);
Then here is my mainController setup:
app.controller('mainController', ['$scope', 'LoginService', function ($scope, LoginService) {
//Controller logic goes here
this.isValid = function (username, password) {
var EmailRegex = /^(([^<>()\[\]\.,;:\s#\"]+(\.[^<>()\[\]\.,;:\s#\"]+)*)|(\".+\"))#(([^<>()[\]\.,;:\s#\"]+\.)+[^<>()[\]\.,;:\s#\"]{2,})$/i;
var PasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/;
var EmailReg = new RegExp(EmailRegex);
var PasswordReg = new RegExp(PasswordRegex);
var em = EmailReg.test(username);
var pas = PasswordReg.test(password);
//alert("Hello dude! Email:" + em + " Password:" + pas + "\n" + username + " " + password );
if (em && pas) {
return false;
}
else {
return true;
}
};
this.user =
{
Message: 'Sign in',
ButtonMessage: 'Sign in Bailey',
TempUser: '',
TempPassword: '',
FirstName: '',
LastName: '',
Role: '',
AuthHash: null,
FinalUser: $scope.Username,
FinalPassword: $scope.Password,
};
$scope.user = this.user;
this.Authenicate = function (Username, Password) {
LoginService.Login(Username, Password).then(function (ResponseData)
{
var readAbleObject = angular.fromJson(angular.fromJson(ResponseData));
$scope.user.FirstName = readAbleObject.FirstName;
$scope.user.LastName = readAbleObject.LastName;
$scope.user.Role = readAbleObject.Role;
$scope.user.AuthHash = readAbleObject.AuthHash;
$scope.user.Username = readAbleObject.Username;
$scope.user.Password = readAbleObject.Password;
$scope.user.Message = "Welcome " + $scope.user.FirstName;
$scope.user.ButtonMessage = "Sign " + $scope.user.FirstName + " " + $scope.user.LastName + " out";
$scope.clearInput();
});
};
$scope.clearInput = function () {
this.user.TempUser = null;
this.user.TempPassword = null;
};
}]);
My html waiting for views to load into them:
<div id="MainDiv" data-ng-app="GApp">
<div id="LoginDiv" class="wrap" data-ng-view="">
</div>
</div>
My .html files content:
<div data-ng-controller="mainController as ctrl">
<div id="HomeHtml">
<link href="Content/Markup/Styles.css" rel="stylesheet" />
<p class="form-title">{{user.Message}}</p>
<form name="login" class="login" novalidate>
<input type="email" placeholder="Susquehanna Software Email" data-ng-model="user.TempUser" />
<input type="password" placeholder="Password" data-ng-model="user.TempPassword" />
<input type="submit" value="{{user.ButtonMessage}}" class="btn btn-lg btn-warning" data-ng-disabled="isValid(user.TempUser, user.TempPassword)" data-ng-click="Authenicate(user.TempUser, user.TempPassword)" />
</form>
</div>

Since you are using controller as syntax, if you write ctrl.user.TempPassword or generally append ctrl before user, then it should work.
You are on the right track, you do not need to write $scope.user = this.user. Its good practice to use controller as syntax.
.when('/', {
templateUrl: 'pages/home.html',
controller: 'mainController',
controllerAs: 'ctrl'
})

for functions to be visible to your view from the controller they need assigning to the $scope object e.g. $scope.Authenticate = this.Authenticate

Related

Angular JS ng-app in multiple spots

I have an angular app with a login page and a signup page and a dashboard that a user is able to access once they have logged in. Currently a user can you directly to the login page or the signup page, so I have a ng-app at the top of both pages. But this does not seem the right way to do things, and it doesn't make sense to initialize my app more than once. But if I only have the ng-app on the login page and a user goes directly to the signup page, the app wont be initialized and I wont have access to the controller for my signup page. How can I get around this?
I would like to just initialize my app once as from what I have read this is how it should be done.
Thank you
Put the ng-app in an index.html file, then have something like this in the body:
<body>
<div data-ui-view></div>
</body>
Then you can use ui-router or ng-route to switch 'states' (ie login, signup etc) and the 'view' will fill into the data-ui-view. Personally I find ui-router to be better, but either can do it.
Most of the time you have to use ng-app once per application. You can manage views using ngRoute module or with ui-router and you can find more options on it.
See example below, there are some extra things you can learn from.
angular.module('demoApp', ['ui.router'])
.run(function($rootScope, $state) {
$rootScope.$on('$stateChangeError', function(evt, to, toParams, from, fromParams, error) {
if (error.redirectTo) {
$state.go(error.redirectTo);
} else {
$state.go('error', {status: error.status})
}
})
})
.factory('userService', userService)
.config(routes);
function userService() {
var usersMock = {
'testUser': {
username: 'testUser',
password: '1234'
},
'testUser2': {
username: 'testUser2',
password: '1234'
}
};
var userService = {
user: undefined,
login: function(userCredentials) {
// later --> $http.post('auth', userCredentials).then(...)
// for demo use local data
var user = usersMock[userCredentials.username]
userService.user = ( user && ( user.password == userCredentials.password ) ) ?
user : undefined;
return user;
},
logout: function() {
userService.user = undefined;
}
}
return userService;
}
function routes($urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('root', {
url: '',
abstract:true,
resolve: {
'user': function(userService) {
return userService.user; // would be async in a real app
}
},
views: {
'': {
templateUrl: 'layout.html',
},
'header#root': {
template: '<h1>header View<span ng-if="user"><button ng-click="logout()">logout</button></span><span ng-if="!user"><button ng-click="login()">login</button></span></h1>',
controller: function($scope, $state, user, userService) {
$scope.user = user;
$scope.login = function() {
$state.go('login');
};
$scope.logout = function() {
userService.logout();
$state.go('root.home', {}, {reload: true});
};
}
},
'footer#root': {
template: '<p>footer view</p>'
}
}
})
.state('root.home', {
url: '/',
views: {
'content': {
template: 'Hello at home'
}
}
})
.state('root.about', {
url: '/about',
views: {
'content': {
template: 'about view'
}
}
})
.state('root.restricted', {
url: '/restricted',
resolve: {
auth: function(userService, $q, $timeout) {
var deferred = $q.defer();
/* //with an async
return UserService.load().then(function(user){
if (permissionService.can(user, {goTo: state})) {
return deferred.resolve({});
} else {
return deferred.reject({redirectTo: 'some_other_state'});
}
}*/
$timeout(function() {
if ( angular.isUndefined(userService.user) ) {
return deferred.reject({redirectTo: 'login'});
}
else {
return deferred.resolve(userService.user);
}
});
return deferred.promise;
}
},
views: {
'content': {
template: 'this is only visible after login. Hello {{user}}!',
controller: function($scope, auth) {
$scope.user = auth.username;
}
}
}
})
.state('login', {
url: '/login',
templateUrl: 'views/login.html',
controller: function($scope, $state, userService) {
$scope.login = function(cred) {
var user = userService.login(cred);
if (angular.isUndefined(user)) {
alert('username or password incorrect.')
}
else {
$state.go('root.restricted');
}
};
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.js"></script>
<div ng-app="demoApp">
<a ui-sref="root.home" href="#">home</a>
<a ui-sref="root.about" href="#">about</a>
<a ui-sref="root.restricted" href="#">restricted page</a>
<div ui-view>
</div>
<script type="text/ng-template" id="views/login.html">
<h1>Login</h1>
<label>Username</label><input ng-model="userCred.username"/>
<label>Password</label><input type="password" ng-model="userCred.password"/>
<button ng-click="login(userCred)">login</button>
</script>
<script type="text/ng-template" id="layout.html">
<div>
<div ui-view="header"></div>
<div ui-view="content"></div>
<div ui-view="footer"></div>
</div>
</script>
</div>

Angular login/logout function not called

I am using angular with JWT token to authenticate the users.
But i am facing an issue that login() which is assigned to $scope is not called. Any help would be appreciated.
app.js file
var admin = angular.module('admin',['admin.core','admin.auth']);
angular.module('admin.core', ['ui.router','satellizer','ngResource','ngAnimate',
'ngStorage']);
admin.config(function($httpProvider, $stateProvider, $urlRouterProvider,
$authProvider, $provide, $locationProvider) {
$authProvider.loginUrl = '/api/authenticate';
$urlRouterProvider.otherwise('/login');
$locationProvider.html5Mode(true);
$stateProvider
.state('login', {
url: '/login',
templateUrl: '/partials/admin/login.html',
title : 'Admin Login'
})
});
angular.module("admin.auth", []).controller("AuthController",AuthController);
function AuthController($auth, $state, $http, $rootScope, $scope) {
console.log("Auth Called");
$scope.email='';
$scope.password='';
$scope.newUser={};
$scope.loginError=false;
$scope.loginErrorText='';
$scope.login = function() {
var credentials = {
email: $scope.email,
password: $scope.password
}
$auth.login(credentials).then(function() {
return $http.get('/api/authenticate/user');
}, function(error) {
$scope.loginError = true;
$scope.loginErrorText = error.data.error;
}).then(function(response) {
if(typeof response != "undefined"){
var user = JSON.stringify(response.data.user);
localStorage.setItem('user', user);
$rootScope.authenticated = true;
$rootScope.currentUser = response.data.user;
$scope.loginError = false;
$scope.loginErrorText = '';
$state.go('dashboard');
}
});
}
$scope.logout = function() {
$auth.logout().then(function() {
// Remove the authenticated user from local storage
localStorage.removeItem('user');
// Flip authenticated to false so that we no longer
// show UI elements dependant on the user being logged in
$rootScope.authenticated = false;
// Remove the current user info from rootscope
$rootScope.currentUser = null;
$state.go('login');
});
}
}
And i am trying to use AuthConrtoller like as
<body ng-controller="AuthController">
<ui-view></ui-view>
</body>
and login.html is
<form name="loginForm" autocomplete="off" novalidate>
<md-input-container class="md-block">
<label for="email">Username</label>
<input type="text" name="email" required="required" ng-model="email" md-no-asterisk/>
<div ng-messages="loginForm.email.$error" role="alert">
<div ng-message="required">Username is required</div>
</div>
</md-input-container>
<md-input-container class="md-block">
<label for="password">Password</label>
<input type="password" name="password" required="required" ng-model="password" md-no-asterisk/>
<div ng-messages="loginForm.password.$error" role="alert">
<div ng-message="required">Password can not be blank</div>
</div>
</md-input-container>
<md-button type="submit" class="md-primary md-raised" ng-disabled="!loginForm.$valid" ng-click="login()">Login</md-button>
</form>
You need to add the controller in route config,
$stateProvider
.state('login', {
url: '/login',
templateUrl: '/partials/admin/login.html',
controller : 'AuthController',
title : 'Admin Login'
})
});
You can handle the login/logout feature using a service and call the functions inside various controller.
DEMO
var app = angular.module('app', []);
app.controller('loginController',['$scope', 'MyUser',function($scope, MyUser)
{
$scope.isloggedin = MyUser.getStatus();
alert($scope.isloggedin);
}]);
app.service('MyUser', [function($scope) {
this.loggedIn = false;
return {
getStatus: function() {
this.loggedIn = true;
return this.loggedIn;
}
}
}]);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body ng-app="app" ng-controller="loginController">
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular.js"></script>
</body>
</html>

AngularJS: How to update Variable Values while using Routing

i want to set the flag icon inside the header of my page depending on the selected language, using AngularJS. The language is selected in another .htm-file and its all brought together by AngularJS-routing.
My application uses one controller named "appController". The controller is inserted into the body-tag in "index.html". Inside "index.html" there is a that uses the angular function "setPicUrl()". The value of "appLang" is set by the radio-input in "language.htm", which is inserted into using routing by AngularJS.
The problem is, that the path for the flag icon does not change when i select another language (the variable "appLang" does). The icon is loaded correctly when i start the application.
routing.js
var app = angular.module("angApp", ["ngRoute"]);
app.config(function ($routeProvider) {
$routeProvider
.when("/visualization", {
templateUrl: "htm/visualization.htm",
controller: "appController"
})
.when("/data", {
templateUrl: "htm/data.htm",
controller: "appController"
})
.when("/social", {
templateUrl: "htm/social.htm",
controller: "appController"
})
.when("/about", {
templateUrl: "htm/about.htm",
controller: "appController"
})
.when("/language", {
templateUrl: "htm/language.htm",
controller: "appController"
});
});
controller.js
app.controller("appController", function ($scope, $http, $location) {
$scope.appLang = "english";
$scope.setPicUrl = function () {
if ($scope.appLang === "german") {
return "icons/german.png";
} else if ($scope.appLang === "english") {
return "icons/english.png";
} else {
//TODO Error handling
return;
}
};
index.html
<body ng-app="angApp" ng-controller="appController">
...
<li ng-class="{ active: headerIsActive('/language')}"><a href="#language"><img id="langpic"
ng-src="{{setPicUrl()}}"
class="img-responsive"></a>
...
<div ng-view></div>
</body>
language.htm
<div class="panel panel-default">
<div class="panel-heading">Spracheinstellungen</div>
<div class="panel-body">
<form>
Wählen Sie ihre Sprache aus:
<br/>
<input type="radio" ng-model="appLang" value="german">Deutsch
<br/>
<input type="radio" ng-model="appLang" value="english">Englisch
</form>
</div>
</div>
Thanks for your help! I got a solution:
The problem was, that the controller has been a copy of "appController" in each view and therefore the variables were different ones with the same name and the different views had no access to the same variable.
Now i use a service to share variables with other controllers and use an own controller for each view.
service:
app.factory("sharedProperties", function () {
return {
appLanguage: ""
};
});
langController:
app.controller("langController", function ($scope, sharedProperties) {
$scope.updateSharedProperties = function (){
sharedProperties.appLanguage = $scope.language;
console.log("--> updateSharedProperties(): " + $scope.language);
};
});
headerController:
app.controller("headerController", function ($scope, $http, $location, sharedProperties) {
$scope.setPicUrl = function () {
if (sharedProperties.appLanguage === "german") {
return "icons/german.png";
} else if (sharedProperties.appLanguage === "english") {
return "icons/english.png";
} else {
//TODO Error handling
return;
}
};
});
HTML for changing language (using langController):
<form>
Wählen Sie ihre Sprache aus:
<br/>
<input type="radio" ng-model="language" value="german" ng-click="updateSharedProperties()">Deutsch
<br/>
<input type="radio" ng-model="language" value="english" ng-click="updateSharedProperties()">Englisch
</form>
HTML for displaying flag-icon in header (using headerController):
<li><img id="langpic" ng-src="{{setPicUrl()}}" class="img-responsive"></li>
Try this. You need to execute the setPicUrl:
<input type="radio" ng-click="setPicUrl()" ng-model="appLang" value="german">Deutsch
<br/>
<input type="radio" ng-click="setPicUrl()" ng-model="appLang" value="english">Englisch
Change:
<img id="langpic" ng-src="{{setPicUrl()}}" class="img-responsive">
To:
<img id="langpic" ng-src="icons/{{appLang}}.png" class="img-responsive">
You can use $routeChangeStart or $routeChangeSuccess which are AngularJS built-in functions in bootstrapping function. For example when the route has been changed $routeChangeSuccess will be called automatically and you can change your $rootScope, $localStorage and any other directive's variables.
Try like this code:
//Bootstrapping Func
app.run(function ($window, $rootScope, $location, $route, $localStorage)
{
$rootScope.appLang = "english";
$rootScope.iconLang = "icons/english.png";
// On Route Change End Event
//---------------------------------------------
$rootScope.$on('$routeChangeSuccess', function ()
{
if ($rootScope.appLang === "german") {
$rootScope.iconLang = "icons/german.png";
} else if ($rootScope.appLang === "english") {
$rootScope.iconLang = "icons/english.png";
} else {
//TODO Error handling
}
});
}
Now you can bind the $rootScope.iconLang to the image tag you want like $scope.iconLang.

Error: [$injector:modulerr] with angular JS [GULP CONTEXT]

first of all , i know this error seems to be famous and i should be able to get the solution with google easily but unfortunately none of the links i read did help me to solve the problem...
I underline the fact i use gulp to minify the Javascript.
Basically this is my module:
(function () {
var app = angular.module('meanApp', ['ngRoute']);
app.config (function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'home/home.view.html',
controller: 'homeCtrl',
controllerAs: 'vm'
})
.when('/register', {
templateUrl: '/auth/register/register.view.html',
controller: 'registerCtrl',
controllerAs: 'vm'
})
.when('/login', {
templateUrl: '/auth/login/login.view.html',
controller: 'loginCtrl',
controllerAs: 'vm'
})
.when('/profile', {
templateUrl: '/profile/profile.view.html',
controller: 'profileCtrl',
controllerAs: 'vm'
})
.otherwise({redirectTo: '/'});
// use the HTML5 History API
$locationProvider.html5Mode(true);
});
app.run(function($rootScope, $location, authentication) {
$rootScope.$on('$routeChangeStart', function(event, nextRoute, currentRoute) {
if ($location.path() === '/profile' && !authentication.isLoggedIn()) {
$location.path('/');
}
});
});
})();
authentication is the following service:
(function () {
angular
.module('meanApp')
.factory('authentication', authentication);
// $inject : To allow the minifiers to rename the function parameters and still be able to inject the right services, the function needs to be annotated with the $inject property. The $inject property is an array of service names to inject.
// https://docs.angularjs.org/guide/di
authentication.$inject = ['$http', '$window'];
function authentication ($http, $window) {
var saveToken = function (token) {
$window.localStorage['mean-token'] = token;
};
var getToken = function () {
return $window.localStorage['mean-token'];
};
var isLoggedIn = function() {
var token = getToken();
var payload;
if(token){
payload = token.split('.')[1];
payload = $window.atob(payload); //will decode a Base64 string
payload = JSON.parse(payload);
return payload.exp > Date.now() / 1000;
} else {
return false;
}
};
var currentUser = function() {
if(isLoggedIn()){
var token = getToken();
var payload = token.split('.')[1];
payload = $window.atob(payload);
payload = JSON.parse(payload);
return {
email : payload.email,
name : payload.name
};
}
};
//An interface between the Angular app and the API, to call the login and register end-points and save the returned token. This will use the Angular $http service
// strict mode :
var register = function(user) {
console.log("ARNAUD: Arriving in register promise");
return $http.post('/api/register', user).success(function(data){
saveToken(data.token);
});
};
var login = function(user) {
return $http.post('/api/login', user).success(function(data) {
saveToken(data.token);
});
};
var logout = function() {
$window.localStorage.removeItem('mean-token');
};
/* console.log("currentUser:"+currentUser);
console.log("saveToken:"+saveToken);
console.log("getToken:"+getToken);
console.log("isLoggedIn:"+isLoggedIn);
console.log("register:"+register);
console.log("login:"+login);
console.log("logout:"+logout);*/
return {
currentUser : currentUser,
saveToken : saveToken,
getToken : getToken,
isLoggedIn : isLoggedIn,
register : register,
login : login,
logout : logout
};
}
})();
A controller:
(function () {
angular
.module('meanApp')
.controller('registerCtrl', registerCtrl);
registerCtrl.$inject = ['$location', 'authentication'];
function registerCtrl($location, authentication) {
console.log("ARNAUD : inside registerCtrl, initializing the properties to empty");
var vm = this;
vm.credentials = {
name : "",
email : "",
password : ""
};
vm.onSubmit = function () {
console.log('ARNAUD : arriving in vm.Submit');
authentication
.register(vm.credentials)
.error(function(err){
alert(err);
})
.then(function(){
$location.path('profile');
});
};
}
})();
my index.html:
<!DOCTYPE html>
<html ng-app="meanApp">
<head>
<title>MEAN stack authentication example</title>
<base href="/">
<link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="/lib/bootstrap/css/bootstrap-theme.min.css">
</head>
<body ng-view>
<script src="lib/angular/angular.min.js"></script>
<script src="lib/angular/angular-route.min.js"></script>
<script src="app.min.js"></script>
</body>
</html>
Thanks a lot for your help
You missed to have to follow minification rule applies to DI on config & run block which should be like below. I'd suggest you to follow Inline Array Annotation method of DI which injecting dependency.
Code
(function () {
var app = angular.module('meanApp', ['ngRoute']);
app.config (['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
//code as is
}
]);
app.run(['$rootScope', '$location', 'authentication',
function($rootScope, $location, authentication) {
//code as is
}
]);
})();
See the warning specified here in DOCS

Pass data from angular form to another controller

I am new to angularjs. I want to pass data from html form to another route.
Here is the part of index.html
<div ng-app="myApp" ng-controller="HomeController">
<div class="container">
<div class="row">
<div class="col-md-12">
<div ng-view=""></div>
</div>
</div>
</div>
</div>
Here are the routes
var myApp = angular.module('myApp', ['ngRoute']);
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'views/home.html',
controller: 'HomeController'
});
$routeProvider.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutController'
});
}]);
When the route is / it hits the views/home.html in which it has a form
<form action="#/about" ng-submit="submitData()">
<input type="text" name="address" ng-model="user.address" />
<input type="submit" />
</form>
I have a user service whose implementation is
myApp.factory("user", function () {
return {};
});
I inject user service in HomeController like
myApp.controller("HomeController", function ($scope, user) {
$scope.user = user;
// and then set values on the object
// $scope.user.address = "1, Mars"; // when uncomment this line it can be accessed on AboutController? Why? Otherwise I cannot access user.address
console.log($scope.user);
});
Don note my comment in above code..
and passes user to AboutController like
myApp.controller("AboutController", function ($scope, user) {
$scope.user = user;
// and then set values on the object
$scope.user.firstname = "John";
$scope.user.secondname = "Smith";
console.log($scope.user);
});
Here is the about.html
<p>
{{ user.address }}
</p>
Problem: {{user.address}} doesn't work on AboutController. I can't see any output... But when i remove the comment from above code.. It only displays hardcoded values in the controller What am I missing?
This is the working demo http://ashoo.com.au/angular/#/
At the moment, all your service does is pass a blank object return {}, to any controller into which it is injected. You need a getter/setter approach, so that in your Home view you can set the data, and in your About view you can retrieve it.
So your service could look something like this:
myApp.factory("user", function () {
var dataObj = {};
return {
setData: function(data) {
dataObj.username = data.username;
},
getData: function() {
return dataObj;
}
};
});
Now you can set the data in your Home controller:
myApp.controller("HomeController", function ($scope, user) {
$scope.submitData = function(data) { //pass in ng-model
user.setData(data); //call 'user' service to set data
}
});
And call it from your About controller:
myApp.controller("AboutController", function ($scope, user) {
$scope.user = user.getData(); //Assign
console.log($scope.user.username);
});
And you html would look like:
<form action="#/about" ng-submit="submitData(user.username)">
<input type="text" name="address" ng-model="user.username" />
<input type="submit" />
</form>

Categories