firebaseSimpleLogin: $createUser Promise Not Resolving until Another Event Occurs - angularjs

I'm setting up registration/login functionality using angular, Firebase, and firebaseSimpleLogin. After reading over a few tutorials and another Stack Overflow thread, I've got the registration working with one small but important caveat: the promise on the SimpleLogin $createUser function isn't resolving until I click on a link or button on my html page. Here's my code:
Register.html
<div class="form-group" >
<label class="control-label" for="email">Email</label>
<input class="form-control" type="text" name="email" id="email" ng-model="cred.email"/>
<label class="control-label" for="password">Password</label>
<div class="form-group">
<input class="form-control" type="password" name="password" id="password" ng-model="cred.password"/>
</div>
<div class="form-group">
<input type="submit" value="Register" class="btn btn-primary" ng-click="register()"/>
</div>
</div>
Main.Js
angular.module('myApp')
.controller('AuthCtrl',
['$scope',
'$location',
'$firebase',
'$firebaseSimpleLogin',
'loginService',
function AuthCtrl($scope, $location, $firebase, $firebaseSimpleLogin,
loginService) {
$scope.register = function(){
var user = {
email: $scope.cred.email,
password: $scope.cred.password
};
loginService.register(user);
};
});
loginService.js (note FBURL is defined elsewhere)
angular.module('myApp')
.factory('loginService', function($firebaseSimpleLogin, $rootScope, $location,
$timeout) {
var ref = new Firebase(FBURL);
var auth = $firebaseSimpleLogin(ref);
return {
register: function (user) {
return auth.$createUser(user.email, user.password)
.then(function(registeredUser) {
console.log(registeredUser);
}
)}
});
In the above loginService.js, I'm not seeing the console.log until I click a button or element; however, the user is created in the Firebase Simple Login DB when I look online. As soon as I click a button or element, the console.log shows. My guess as to the issue is that the promise from auth.$createUser() isn't getting resolved, but I cannot find out why that would be.

Related

Server side validation for multiple fields in Angular

I have form where I need validation on server side. Backend use one request to validate multiple fields.
I try to add validation message after response. Here is example:
This is my html code:
<div ng-app="MyApp">
<div ng-controller="MyController">
<form name="MyForm" novalidate ng-submit="send()">
<div>
<label>Email</label>
<input type="email" name="email" ng-model="user.email" required>
<div ng-show="MyForm.email.$invalid">error message</div>
</div>
<input type="submit" ng-disabled="MyForm.$invalid">
<pre>{{ MyForm.email.$error | json }}</pre>
</form>
</div>
</div>
And my js code:
var myApp = angular.module('MyApp', []);
myApp.controller("MyController", ['$scope', '$timeout', '$log', function($scope, $timeout, $log) {
$scope.user = { "email" : "" }
$scope.send = function() {
$timeout(function() {
$log.log("Response from server. Multiple fields validation.");
$scope.MyForm["email"].$setValidity("server-side-error", false, $scope.MyForm)
// here I want to add something what listen once on $scope.MyForm["email"] changed
}, 1000);
};
}]);
But I need remove error when value changed. How to achieve it using Angular?
Here is example: https://jsfiddle.net/9wqhd89z/
You can call a check function whenever the user change the input using ng-change. So it will check if the email is currently invalid, and if it is it will set as valid again.
<input type="email" name="email" ng-model="user.email" ng-change="check()" required>
$scope.check = function(){
if ($scope.MyForm.email.$valid == false){
$scope.MyForm.email.$setValidity('server-side-error', true);
}
}
You can find a working version in this jsFiddle

Post angularjs form to nodejs Express ( Bad request)

im new in angularJs, im trying to make a basic login with angularJS and nodejs ( server side), i dont care about security for now im just trying to learn how to post. so i made a login form and a controller with angular :
My Login Form :
<div class="col-md-4">
<h1>Login</h2>
<form class="form" >
<div class="form-group">
<label>Username</label>
<input type="email" class="form-control" ng-model="login.mail" required>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" ng-model="login.password" required>
</div>
<div>
<button type="text" class="btn btn-default" ng-click="login()">Login</button>
</div>
</form>
</div>
then my router & controller Angularjs :
'use strict';
angular.module('login', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/login', {
templateUrl: 'views/login.html',
controller: 'loginCtrl'
});
}])
.controller('loginCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.login = function() {
$http.post('/api/users/login', $scope.login).success(function (response) {
console.log(response);
// refresh();
});
};
}]);
and Server side i have that :
router.post('/login/', function(req, res) {
// here "/login/" means "/users/login" ( in index of controllers)
console.log(req.body.mail);
var usermail = req.body.mail;
var pass = req.body.password;
console.log(usermail + pass);
User.find({mail: usermail}, function(err, user) {
if (err) {
res.send(err);
console.log("ça marche pas")
} else {
res.json( user );
console.log(user);
}
})
});
server side : it works ( when i use DHC chrome extension to Post) but when im using angularjs view i got that error :
POST http://localhost:3000/api/users/login 400 (Bad Request)
Please help me to solve that, i think i missed something. Thank you in advance.
I think you are sending your login function as in below line:
$http.post('/api/users/login', $scope.login)
You probably want to pass a parameter in your login function that can be sent to server as below:
$scope.login = function(loginData) {
$http.post('/api/users/login', loginData).success(function (response)
Update
You are assigning your form values to $scope.login. If you would create a separate variable for it, for example loginForm, you can send this as valid JSON to your API:
<div class="col-md-4">
<h1>Login</h2>
<form class="form" >
<div class="form-group">
<label>Username</label>
<input type="email" class="form-control" ng-model="loginForm.mail" required>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" ng-model="loginData.password" required>
</div>
<div>
<button type="text" class="btn btn-default" ng-click="login(loginData)">Login</button>
</div>
</form>
</div>
And .js:
.controller('loginCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.loginForm = {
mail: '',
password: ''
};
$scope.login = function(loginData) {
// Check what this prints out:
console.log(loginData);
$http.post('/api/users/login', loginData).success(function (response) {
console.log(response);
// refresh();
});
};
}]);

Angularjs scope not working

I am using basic angular.js concept to show and hide a div. For some reasons I am unable to make it work.
While Uploading a file I am showing a div 'myFormSpinner' on the basis of registerStart value. I am creating a phone gap app.
Could someone please help me in finding the issue. Apart from showing/hiding div everything works fine. Below is the code snippet:
<div class="row" ng-controller="RegisterCtrl">
<div id="myFormSpinner" ng-show="registerStart">
<img src="img/ajax-loader.gif">
</div>
<div class="col-md-8">
<form class="ng-pristine ng-invalid ng-invalid-required" style="margin-top:5%;">
<div class="col-md-6">
<input class="form-control " type="text" ng-model="registerData.Email" id="Email" name="Email" required placeholder="Email">
</div>
<div class="col-md-offset-1 col-md-10 ">
<input type="submit" ng-click="register()" value="Register" class="btn btn-default btn-primary">
</div>
</form>
</div>
event.controller('RegisterCtrl', ['$scope', '$state', '$q', '$http', 'eventService', 'authService', '$stateParams', '$rootScope', 'tokenService', 'imageService', 'spinnerService', 'appBackgroundService',
function ($scope, $state, $q, $http, eventService, authService, $stateParams, $rootScope, tokenService, imageService, spinnerService, appBackgroundService) {
var userNumber = 0;
$scope.mediaUploadStart = false;
$scope.eventId = $state.params.id;
$scope.register = function () {
$scope.registerStart = true;
console.log('scope.Pic=' + $scope.pic);
if ($scope.registerData.Email) {
spinnerService.show('myFormSpinner');
$scope.mediaUploadStart = true;
var paramOptions = {
eventId: $state.params.id,
email: $scope.registerData.Email,
fb: {},
number: userNumber,
provider: "Form"
};
uploadPicAndData(paramOptions).then(function (result) {
var data = JSON.parse(result);
$scope.registerStart = false;
appBackgroundService.disableBackgroundMode();
},
function (error) {
spinnerService.hide('myFormSpinner');
$scope.registerStart = false;
appBackgroundService.disableBackgroundMode();
});
$scope.mediaUploadStart = false;
spinnerService.hide('myFormSpinner');
}
};
}])
You are setting the $scope element in an async mode.
the digest cycle is not able to determine that a change has been made to the scope element in an async mode.
You should use $apply to activate the digest cycle.
$scope.$apply(function () { $scope.registerStart = false; });
Read more about $apply here: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

AngularJS Login form with ng-click not working

I wrote a basic login form in this plunk http://plnkr.co/edit/xQEN1ZNN5ZEw1CSwNw97?p=preview (click on the red Log into Dashboard button on the Home route).
However for some reason I cannot get the login() method to fire in my loginCtrl controller code.
Why is this example working, and mine is not ? http://plnkr.co/edit/H4SVl6?p=preview
Instead what it's doing is an old-school URL redirect with the user/password parameters passed in as form variables. I can't figure out what's wrong.
Here is LoginCtrl code as well as the login-form.html template :
(function () {
'use strict';
angular.module('routerApp').controller('LoginCtrl',
['$rootScope', '$scope', authenticate]);
function authenticate($rootScope, $scope, userService) {
var login = this;
login.loginUser = function () {
login.dataLoading = true;
//loginService.authUser(login.user, login.password); // TO DO !!!
};
login.test = function () {
var test = true;
};
}
})();
<div ng-show="error" class="alert alert-danger">{{error}}</div>
<form ng-submit="login.loginUser()" name="form">
<div class="form-group">
<label for="username">Username</label>
<i class="fa fa-key"></i>
<input type="text" name="username" id="username" class="form-control" ng-model="login.username" required />
<span ng-show="form.username.$dirty && form.username.$error.required" class="help-block">Username is required</span>
</div>
<div class="form-group">
<label for="password">Password</label>
<i class="fa fa-lock"></i>
<input type="password" name="password" id="password" class="form-control" ng-model="login.password" required />
<span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">Password is required</span>
</div>
<div class="form-actions">
<button type="submit" ng-disabled="form.$invalid || dataLoading" class="btn btn-danger">Login</button>
<img ng-if="login.dataLoading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=="/>
</div>
</form>
In my local app, it is posting the old-style form variables via the URL, and I cannot get it to fire the login.loginUser function below inside LoginCtrl.
thnk you in advance...
Bob
for some odd reason (perhaps ui-router versioning) the controllerAs is not working.
Diana´s answer is valid, but it doesn´t use the controlleras syntax.
If you still want to use it, change the ui-router setting to:
.state('login', {
url: "/login",
templateUrl: "login-form.html",
controller: 'LoginCtrl as login',
})
That should do the trick ;)
Check it out:
http://plnkr.co/edit/OCqNexVeFFxt4kUuEVc1?p=preview
The controller change I applied is:
angular.module('routerApp').controller('LoginCtrl', function ($rootScope, $scope) {
$scope.loginUser = function () {
$scope.dataLoading = true;
//loginService.authUser(login.user, login.password); // TO DO !!!
};
$scope.test = function () {
var test = true;
};
})
and in the template I removed login. from the ng-if and ng-submit.
Here is a working plunks.

Unit testing an angularjs controller with a form in it

I'm trying to unit test a connection forms controller with karma and jasmine, but on thing I can't get to grips with.
The controller:
.controller('connectionController', ['$scope', '$rootScope', '$state', '$stateParams', '$http', '$localStorage',
function($scope, $rootScope, $state, $stateParams, $http, $localStorage){
$scope.userCredentials = {};
$scope.connectionError = false;
$scope.connectUser=function(){
if ($scope.connectionForm.$valid) {
//Do the login stuff here
//IF good --> state.go...
}
else {
console.log('Invalide.');
$scope.connectionError = true;
}
}
}])
Then in my HTML (simplified to a maximum):
<form name="connectionForm" novalidate>
<div class="form-group input-group" show-errors='{ showSuccess: true }'>
<span for="login" class="input-group-addon"></span>
<input type="text" ng-model="userCredentials.login" required>
</div>
<div class="form-group input-group" show-errors='{ showSuccess: true }'>
<span for="password" class="input-group-addon"></span>
<input type="password" ng-model="userCredentials.password" required>
</div>
<button class="btn btn-primary" ng-click="connectUser()">Connect</button>
</form>
And finally the test (specific 'it' that doesn't pass):
it('should connect user', function(){
scope.userCredentials.login = 'aUser';
scope.userCredentials.password = 'aPassword';
$httpBackend.when('POST', 'http://localhost:4711/api/token').
respond({ token: 'xxx', user: aUser });
scope.connectUser();
$httpBackend.flush();
});
So the the problem I get is that this:
TypeError: Cannot read property '$valid' of undefined
at Scope.$scope.connectUser (connection.js)
at null.<anonymous> (connection.js)
Si I think the basic problem comes from the fact that the controller doesn't have the access to stuff defined only on the html (like connectionForm...) and cannot get their properties.
Another thing to notice is that I do a state.go(..) when the connection was successful, could it be this ?
What can I do ? Or more, what am I doing wrong ?

Resources