I'm following thinkster's ang-news tutorial to build authentication using firebase. I can create users with a service and controller but after registering a new user they are not logged in.
I have a auth.js service:
app.factory('Auth', ['$rootScope', 'FIREBASE_URL', '$firebaseSimpleLogin', function($rootScope, FIREBASE_URL, $firebaseSimpleLogin){
var ref = new Firebase(FIREBASE_URL);
var auth = $firebaseSimpleLogin(ref);
var Auth = {
register: function(user){
return auth.$createUser(user.email, user.password);
},
signedIn: function(){
return auth.user !== null; // user signed in if user property is not null
},
login: function(user){
return auth.$login('password', user); // type of login
},
logout: function(){
auth.$logout();
}
};
$rootScope.signedIn = function(){
return Auth.signedIn();
};
return Auth;
}]);
auth.user always stays null.
This is my controller:
app.controller('AuthCtrl', ['$scope', '$location', 'Auth', function($scope, $location, Auth){
if (Auth.signedIn()){
$location.path('/')
}
$scope.register = function(){
Auth.register($scope.user).then(function(authUser){
console.log('authUser: ' + JSON.stringify(authUser))
$location.path('/');
})
}
}])
Then I have a register.html with an email/password form. It calls register():
<form ng-submit='register()' novalidate>
<input type='email' placeholder='Email' class='form-control' ng-model='user.email'>
<input type='password' placeholder='Password' class='form-control' ng-model='user.password'>
<input type='submit' class='btn btn-success' value='Register'>
</form>
The users get generated in my Firebase Forge, but after I submit the register form, the Logout button does not show:
<ul class='nav navbar-nav navbar-right' ng-show='signedIn()'>
<li>
<a href='#' ng-click='logout()'>Logout</a>
</li>
</ul>
Why does signedIn() stay falsey after I create a user in the firebase forge?
Creating a user does not automatically log them in (though it used to in an older version of angularFire).
Change your controller method to look like:
$scope.register = function(){
Auth.register($scope.user).then(function(authUser){
console.log('authUser: ' + JSON.stringify(authUser))
Auth.login($scope.user);
$location.path('/');
})
}
This will create the user in the Forge and then once that promise resolves, it will automatically log them in.
Related
I'm following a tutorial to create a simple todo app using the MEAN stack. Everything was working fine until I moved the controllers and services into separate files. Now I can create a new todo but it doesn't get the text value. I can see in my mongoDB database that a new entry has been created but it doesn't have a text value. I've been looking all over my code but I can't find anything nor do I get any error or warnings in the developer tools of the browser.
Here is the code for the form:
<div id="todo-form" class="row">
<div class="col-sm-8 col-sm-offset-2 text-center">
<form>
<div class="form-group">
<!-- Bind this value to formData.text in Angular -->
<input type="text" class="form-control input-lg text-center" placeholder="Add a todo" ng-model="formData.text">
</div>
<button type="submit" class="btn btn-primary btn-lg" ng-click="createTodo()">Add</button>
</form>
</div>
</div>
Here is my service:
//todos.js service
//the service is meant to interact with our api
angular.module('todoService', [])
//simple service
//each function returns a promise object
.factory('Todos', function($http){
return {
get : function() {
return $http.get('/api/todos');
},
create : function(todoData){
return $http.post('/api/todos', todoData);
},
delete : function(id){
return $http.delete('/api/todos/' + id);
}
}
});
Here is my main controller which uses the service:
//main.js
var myApp = angular.module('todoController', []);
myApp.controller('mainController', ['$scope', '$http', 'Todos', function($scope, $http, Todos){
$scope.formData = {};
//GET
//get all the todos by using the service we created
Todos.get()
.success(function(data){
$scope.todos = data;
});
//CREATE
$scope.createTodo = function(){
Todos.create($scope.formData)
.success(function(data){
$scope.formData = {};
$scope.todos = data;
});
}
//DELETE
$scope.deleteTodo = function(id){
Todos.delete(id)
.success(function(data){
$scope.todos = data;
});
};
}]);
Lastly, here is the route for creating a todo:
var Todo = require('./models/todos');
//expose our routes to our app with module exports
module.exports = function(app){
//api
//get all todos
app.get('/api/todos', function(req, res){
Todo.find(function(err, todos){
if(err)
res.send(err);
res.json(todos);
});
});
//create to do
app.post('/api/todos', function(req, res){
Todo.create({
text: req.body.text,
done: false
}, function(err, todo){
if(err)
res.send(err);
//get and return all todos after creating the new one
Todo.find(function(err, todos){
if(err)
res.send(err);
res.json(todos);
});
});
});
To recap, for some reason the formData.text value doesn't get stored somewhere and I don't know why.
I can't say for sure with angular but normal HTML forms inputs need a name attribute to submit
I have an idea of how to use post method for login, however, our new requirement is my API team has provided get method. How is this used in angular? Please help me. I am stuck on this problem as I am new to angular. Below is the API for get method:
http://183.82.48/HospitalManagementSystem/Service1.svc/LoginVerification/{EMAILID}/{PASSWORD}
You can try to construct the URI yourself.
<form ng-app="login" ng-controller="loginCtrl">
<span>Email</span><input ng-model="emailId" type="text" required><br>
<span>Password</span><input ng-model="password" type="password" required><br>
<button ng-click="login()">Login</button>
</form>
<script>
var app = angular.module('login', []);
app.controller('loginCtrl', function($scope, $http) {
$scope.login = function() {
$http.get('http://183.82.0.48/HospitalManagementSystem/Service1.svc/LoginVerification/' + $scope.emailId + '/' + $scope.password).then(
function (response) {
console.log(response.data);
// ...
},
function (error) {
console.log(error);
// ...
}
)
}
});
</script>
I need the following functionality: When a user goes to the login form, the browser should auto fill the username and password.
My implementation works (on FF and Chrome) but, there is this bug (not consistent) where the model data does not get updated correctly when switching between users. This means that I log in with user ONE, then log out, and enter the credentials for user TWO, but after I click the login button, I'm still logged in with user ONE.
The login form looks like this:
<form class="form-horizontal" ng-submit="login(credentials)">
<fieldset>
<div class="form-group" ng-class="{'has-error' : validationErrors.email}">
<div class="btn-icon-lined btn-icon-round btn-icon-sm btn-default-light">
<span class="glyphicon glyphicon-envelope"></span>
</div>
<input type="email" name="email" autocomplete="on" ng-model="credentials.email" class="form-control input-lg input-round text-center" placeholder="Email" >
<span class="help-block" ng-if="validationErrors.email">{{ validationErrors.email.0 }}</span>
</div>
<div class="form-group" ng-class="{'has-error' : validationErrors.password}">
<div class="btn-icon-lined btn-icon-round btn-icon-sm btn-default-light">
<span class="glyphicon glyphicon-lock"></span>
</div>
<input type="password" name="password" autocomplete="on" ng-model="credentials.password" class="form-control input-lg input-round text-center" placeholder="Password" >
<span class="help-block" ng-if="validationErrors.password">{{ validationErrors.password.0 }}</span>
</div>
<div class="form-group">
<input type="submit" value="Sign in" class="btn btn-primary btn-lg btn-round btn-block text-center">
</div>
</fieldset>
</form>
The login controller contains something like:
// Login Controller
app.controller( 'LoginCtrl', ['$rootScope','$scope', '$state', 'AppUser', 'Auth',
function($rootScope, $scope, $state, AppUser, Auth){
console.log("LoginCtrl");
$scope.credentials = {
"email" : "",
"password": ""
};
$scope.redirectAfterLogin = function() {
// set user data
AppUser.setUserData($scope.user);
...
}
// Login attempt handler
$scope.login = function(data) {
data = {'user':data};
Auth.login(data,
function(response) {
$scope.user = response.data;
...
},function(response){
$scope.validationErrors = {
"email" : [],
"password": []
};
...
}
);
};
}]);
Logout:
// logout
$scope.logout = function() {
// remove attempted URL, if any
AppUser.removeAttemptUrl();
data = {'user':
{
'email': $scope.user.email
}
};
Auth.logout(data,
function(){
AppUser.unSetUserData($scope.user); // se method below
$state.go(ApplicationState.LOGIN);
},
function(){
console.log("Logout failed");
});
}
angular.module('app.service').factory('AppUser', [
'$window', '$rootScope', 'LocalStorage', 'appConfig', '$injector', '$location',
function($window, $rootScope, localStorage, appConfig, $injector, $location){
// Redirect to the original requested page after login
var redirectToUrlAfterLogin = { url: '' };
var userKey = "AppUser";
var userData = {};
angular.element($window).on('storage', function(event) {
if (event.key === userKey) {
$rootScope.$apply();
}
});
return {
/**
* Redirect to the original requested page after login
* - we need to be able to save the intended URL, request it, remove it and redirect to it
*/
saveAttemptUrl: function() {
if ($location.path().toLowerCase() != ApplicationState.LOGIN) {
redirectToUrlAfterLogin.url = $location.path();
}
else {
redirectToUrlAfterLogin.url = '/';
}
},
getAttemptedUrl: function() {
return redirectToUrlAfterLogin.url;
},
removeAttemptUrl: function() {
// re-initialize URL
redirectToUrlAfterLogin = { url: '' };
},
redirectToAttemptedUrl: function() {
$location.path(redirectToUrlAfterLogin.url);
},
/**
* Returns the current user's state
* #returns {boolean}
*/
isAuthenticated: function() {
userData = JSON.parse(localStorage.get(userKey) || '{}').userData;
if (!this._isSessionExpired()) {
if (userData !== undefined){
return !!(userData.id !== null && userData.email);
}
else{
return false;
}
}
else{
if (userData !== undefined){
var data = {
'user':{
'email': userData.email
}
}
// we use $injector to avoid Circular Dependency which is thrown by injecting the $api service
$injector.invoke(['$api', function($api){
$api.auth.logout(data).success(function(result){
userData = {};
localStorage.remove(userKey);
});
}]);
return false;
}
}
},
getUserData: function() {
return userData;
},
setUserData: function(data) {
userData = data;
localStorage.set(userKey, JSON.stringify({
userData: data,
stamp: Date.now()
}));
},
unSetUserData: function() {
userData = {};
localStorage.remove(userKey);
},
_isSessionExpired: function() {
var session = JSON.parse(localStorage.get(userKey) || '{}');
return (Date.now() - (session.stamp || 0)) > appConfig.sessionTimeout;
},
userData : userData
};
}] );
Any ideas on why this is happening?
After you logout check the localStorage with the browser inspector.
Probably you will find some variable that you didn't clear.
So just clear the storage and it should be fine.
To clear the storage use:
localStorage.clear();
One additional problem it could be you didn't clean the $rootScope if you didn't refresh all the data are still in there.
Is this the problem? userKey doesn't seem to be defined in the code you've showed.
// add userKey param
unSetUserData: function(userKey) {
userData = {};
localStorage.remove(userKey);
},
Hi I'm just learning angular, and I was wondering if someone could let me know what I'm doing wrong with setting up this simple load bar in the Yeoman signup page
In the signup.controller.js, I have the following code:
'use strict';
angular.module('lolBetApp')
.controller('SignupCtrl', function ($scope, $http, Auth, $location) {
$scope.user = {};
$scope.errors = {};
$scope.register = function(form) {
$scope.submitted = true;
if(form.$valid) {
Auth.createUser({
summonerName: $scope.user.summonerName,
email: $scope.user.email,
password: $scope.user.password
})
.then( function() {
// Account created, redirect to home
$location.path('/');
})
.catch( function(err) {
err = err.data;
$scope.errors = {};
// Update validity of form fields that match the mongoose errors
angular.forEach(err.errors, function(error, field) {
form[field].$setValidity('mongoose', false);
$scope.errors[field] = error.message;
});
});
}
};
$scope.$emit('LOAD')
$http.jsonp('http://filltext.com/?rows=10&delay=5&fname={firstName}&callback=JSON_CALLBACK')
.success(function(data){
$scope.people=data;
$scope.$emit('UNLOAD')
});
}).
controller('loaderController',['$scope',function($scope){
$scope.$on('LOAD',function(){$scope.loading=true});
$scope.$on('UNLOAD',function(){$scope.loading=false });
}]);
And in my signup.html, I have the following code:
<div ng-controller="loaderController">
<div class="alert alert-info" ng-show="loading">Summoning...</div>
<div ng-controller="myController">
<ul>
<li ng-repeat="person in people">
{{person.fname}}
</li>
</ul>
</div>
I was able to get this to work easily without using Yeoman, using the code in this link http://plnkr.co/edit/30qbDj0xuBESp6LT8etM?p=info
Does anyone know what I'm doing wrong?
Thanks,
Nevermind! I just got it to work. The problem is that I had the wrong name for the controller in the signup.html page
<div ng-controller="SignupCtrl">
<ul>
<li ng-repeat="person in people">
{{person.fname}}
</li>
</ul>
</div>
I am new to AngularJS and not sure where I am missing, though I know its a minor mistake which I am committing. Please help me out with below scenario.
I have a form where in I write a post {textArea} and click submit button, which calls ng-click=createPost() method.
It goes to controller.js which is:
app.controller('MyCtrl1', ['$scope', 'PostFactory', '$location', function ($scope, PostFactory, $location) {
/* callback for ng-click 'createUser': */
$scope.createPost = function() {
alert("in createPost" + $scope.post.postText);
alert("in createPost" + $scope.post);
PostFactory.create($scope.post)
$scope.posts.push($scope.post.postText);
$scope.post = "";
$location.path('/view1');
}
$scope.posts = PostFactory.query();
/*UserFactory.get({}, function (userFactory) {
$scope.firstname = userFactory.firstName;
})*/
}]);
and my service.js is:
var services = angular.module('ngdemo.services', ['ngResource']);
//alert("In services");
services.factory('PostFactory', function ($resource) {
// alert("Reached services.js");
return $resource('/ngdemo/web/posts', {}, {
query: {
method: 'GET',
//params: {},
isArray: true
},
create: {method: 'POST'}
})
});
my Spring controller which is exposed as service and have post method:
#RequestMapping(/*value = "/add",*/ method = RequestMethod.POST)
public #ResponseBody String addPost(#ModelAttribute(value = "") Post post, BindingResult result) {
System.out.println("Post value : " + post.getPostText());
//post.setPostId();
post.setPostTags("#dummy");
postService.addPost(post);
return "redirect:/";
}
my form :
<form novalidate="novalidate" class="form-horizontal">
<!-- Textarea -->
<div class="form-group">
<div class="col-md-4">
<textarea ng-model="post.postText" rows="4" cols="300" name="inputQuestion" id="post.postText" class="form-control expand" placeholder="What you want to pingle today?"></textarea>
</div>
<br>
<!-- Button -->
<div class="col-md-4">
<button ng-click='createPost()' class="btn btn-default plus"> Pingle it! </button>
</div>
</div>
</form>
Problem is : always Post value in controller is coming as null, have tried with $scope.post and $scope.postText but no joy!
Please let me know where I am missing?????
UPDATE:
How can we pass a form object to Spring Controller in controller.js?? Post is my Domain object
it worked, once I replaced #ModelAttribute with #RequestBody, somehow it was preventing the data to be populated in my object. After setting #RequestBody, it worked!Thanks all!