Upload a picture in signup with Firebase - javascript

I am using Firebase.auth to sign up users on my website.
In order to get more informations from them, I also create a Firestore Document that stores more informations. Here is my code:
HTML
<div class="col-md-6">
<div class="row justify-content-center align-items-center h-md-100vh">
<div class="col-10 my-5 my-md-0">
<h2 class="h4 font-weight-bold">Signup To Become A Player</h2>
<form id="player-login-form">
<div class="form-group">
<input type="text" id="player-signup-firstname" name="player_signup[firstname]" required="required" placeholder="What's your firstname?" class="form-control">
<div class="invalid-feedback mt-0"></div>
</div>
<div class="form-group">
<input type="text" id="player-signup-lastname" name="player_signup[lastname]" required="required" placeholder="What's your lastname" class="form-control">
<div class="invalid-feedback mt-0"></div>
</div>
<div class="form-group">
<input type="email" id="player-login-email" name="player_signup[email]" required="required" placeholder="What's your email?" class="form-control">
<div class="invalid-feedback mt-0"></div>
<small id="emailHelp" class="form-text text-muted"></small>
</div>
<div class="form-group ">
<input type="password" id="player-login-password" name="player_signup[password]" required="required" placeholder="Set a password" class="form-control">
<div class="invalid-feedback mt-0"></div>
</div>
<div class="form-group ">
<input type="file" accept="image/*" capture="camera" id="cameraInput">
</div>
<button type="submit" class="btn btn-primary" id="player-signup-button">Create account</button>
</form>
</div>
</div>
</div>
And JS
// The sign up variables and constants
const signUpBtn = document.querySelector('#player-signup-button');
// Sign up function
signUpBtn.addEventListener("click", (e) => {
e.preventDefault(); // avoid the page to refresh when we click signup
// get user info from the id of the input
const loginForm = document.querySelector('#player-login-form');
const firstname = loginForm['player-signup-firstname'].value;
const lastname = loginForm['player-signup-lastname'].value;
const email = loginForm['player-login-email'].value;
const password = loginForm['player-login-password'].value;
// Upload picture part
var refname = 'photos/' + firstname + lastname;
let storageRef = firebase.storage().ref(refname);
let fileUpload = document.getElementById("cameraInput")
fileUpload.addEventListener('change', function(evt) {
console.log("Is code going here?");
let firstFile = evt.target.files[0] // upload the first file only
let uploadTask = storageRef.put(firstFile).then(function(fileSnapshot) {
firebase.firestore().collection('players').add({
firstname: firstname,
lastname: lastname,
email: email,
profilepic: fileSnapshot.ref.getDownloadURL()
});
})
});
auth.createUserWithEmailAndPassword(email, password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
M.toast({html:error.message});
}).then( cred => {
loginForm.reset();
});
});
**My question: ** I have issues for the image uploading part. It looks like the code inside fileUpload.addEventListener is not read by the interpreter.
Do you have any ideas where is the issue?

You need to put this callback registration outside the click handler:
document.getElementById("cameraInput").addEventListener('change', function(evt) {...});
Right now your code says "after the user submits the form, start listening for them to browse for a picture" when what you really want is "when the page loads, start listening for the user to browse for a picture. Afterwards, when they submit the form read the selected picture file and send it to the server."

Related

Retrieving Data from Local Storage - key value pairs apparently don't match (error)

I am trying to make a functional login and registration pages (I know that in real life I need to store the login info in a database but for now I would like to see my pages "working"). I created two pages with forms one for registration and one for login. I also have two JS files one for locally storing input values (registerDetails.js) and one for retrieving those values during login (login.js).
Storing the information is not a problem, however, when I try to log in with the information I have just inputted and know it's correct it still throws an "Error" at me to say that password and username don't match even though I know they do match.
SOLUTION IN THE COMMENTS - MIX UP OF VARIABLES
I even tried to error handle if there is a problem with browser compatibility, still to no avail.
This is HTML for register.html:
<form class="form-horizontal">
<fieldset>
<div id="legend">
<legend>
Register or <a class="login-link" href="login.html">Login</a>
</legend>
<p>All fileds marked with * are required.</p>
</div>
<hr />
<div class="control-group">
<!-- Username -->
<label class="control-label" for="username"><span class="asterisk">*</span> Username</label>
<div class="controls">
<input type="text" id="username" name="username" placeholder="Any letters or numbers without spaces"
class="input-xlarge" />
</div>
<br />
</div>
<div class="control-group">
<!-- E-mail -->
<label class="control-label" for="email"><span class="asterisk">*</span> E-mail</label>
<div class="controls">
<input type="text" id="email" name="email" placeholder="Enter your email here" class="input-xlarge" />
</div>
<br />
</div>
<div class="control-group">
<!-- Password-->
<label class="control-label" for="password"><span class="asterisk">*</span> Password</label>
<div class="controls">
<input type="password" id="password" name="password" placeholder="Password of atleast 4 characters"
class="input-xlarge" />
</div>
<br />
</div>
<div class="control-group">
<!-- Password -->
<label class="control-label" for="password_confirm"><span class="asterisk">*</span> Confirm Password</label>
<div class="controls">
<input type="password" id="password_confirm" name="password_confirm" placeholder="Please confirm password"
class="input-xlarge" />
</div>
<br />
</div>
<div class="control-group">
<!-- Button -->
<div class="controls">
<button type="submit" id="register" class="btn btn-success" onClick="store()">
Register
</button>
</div>
</div>
</fieldset>
</form>
Here is my HTML for login.html:
<form class="form-horizontal">
<fieldset>
<div id="legend">
<legend>
Login or <a class="login-link" href="register.html">Register</a>
</legend>
</div>
<hr />
<div class="control-group">
<!-- Username or Email-->
<label class="control-label" for="username">Username or Email</label>
<div class="controls">
<input type="text" id="usernameEmail" name="usernameEmail" placeholder="Enter your email or username"
class="input-xlarge" />
</div>
<br />
</div>
<div class="control-group">
<!-- Password-->
<label class="control-label" for="password">Password</label>
<div class="controls">
<input type="password" id="passwordLogin" name="password" placeholder="Enter your password"
class="input-xlarge" />
</div>
<br />
</div>
<div class="control-group">
<!-- Button -->
<div class="controls">
<button class="btn btn-success" type="submit" onclick="check()">Login</button>
</div>
</div>
</fieldset>
</form>
My registration JS works fine, the browser prompts me to save credentials for later use...
Which is here:
// Getting details from the registration form to later store their values
var userName = document.getElementById('username');
var userEmail = document.getElementById('email');
var password = document.getElementById('password');
var passwordConfirm = document.getElementById('password_confirm');
// Locally storing input value from register-form
function store() {
if (typeof (Storage) !== "undefined") {
localStorage.setItem('name', userName.value);
localStorage.setItem('email', userEmail.value);
localStorage.setItem('password', password.value);
localStorage.setItem('password_confirmation', passwordConfirm.value);
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support Web Storage...";
}
}
My login page, however, throws the ERROR alert, even when I know for sure that the username and password match.
// check if stored data from register-form is equal to entered data in the login-form
function check() {
// stored data from the register-form
var storedName = localStorage.getItem('name');
// var storedEmail = localStorage.getItem('email');
var storedPassword = localStorage.getItem('password');
// entered data from the login-form
var userNameLogin = document.getElementById('usernameEmail');
var userPwLogin = document.getElementById('passwordLogin');
// check if stored data from register-form is equal to data from login form
if (userNameLogin.value == storedName && storedPassword.value == userPwLogin) {
alert('You are loged in.');
} else {
alert('ERROR.');
}
}
I have spent a few hours trying to rewrite the code to maybe see some typos or mistakes but I cannot find where I am going wrong! If anyone could help out as to show the reason why it does not match the username and password would be great.
It should alert me "You are logged in."
Thanks!
You have a typo
if (userNameLogin.value == storedName && storedPassword.value == userPwLogin) {
^^Here
}
Should be this instead
if (userNameLogin.value == storedName && userPwLogin.value == storedPassword ) {
}
By the way, your code will only log in with username (and not email) as it is. Don't forget to compare the email too.
Variables that are meant to store your elements at register page(userName, userEmail, etc.) might be null when store() is called.
I would suggest to get those inside the function:
function store() {
var userName = document.getElementById('username');
var userEmail = document.getElementById('email');
var password = document.getElementById('password');
var passwordConfirm = document.getElementById('password_confirm');
if (typeof (Storage) !== "undefined") {
localStorage.setItem('name', userName.value);
localStorage.setItem('email', userEmail.value);
localStorage.setItem('password', password.value);
localStorage.setItem('password_confirmation', passwordConfirm.value);
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support Web Storage...";
}
}
But the solution lies in this line:
if (userNameLogin.value == storedName && storedPassword.value == userPwLogin)
In your case storedPassword doesn't have "value" and userPwLogin does, since userPwLogin is the element on your form
Your code isn't working right because you've mixed up your local storage variable with your input elements. This line:
if (userNameLogin.value === storedName && storedPassword.value === userPwLogin) {
it should be:
if (userNameLogin.value === storedName && userPwLogin.value === storedPassword) {

How to fix "Too Many Redirects" error in HTTP

I'm trying to set up a login/signup website (Using Firebase Auth), and I am getting a "too many redirects" error when I try to sign up on my site. How can I fix this?
Running HTML5 with Firebase Auth
<form action="index.html" style="border:1px solid #ccc">
<div class="container">
<h1>Sign Up</h1>
<p>Please fill in this form to create an account.</p>
<hr>
<label for="email"><b>Email</b></label>
<input type="text" placeholder="Enter Email" name="email" required>
<br>
<label for="psw"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="psw" required>
<br>
<p>By creating an account you agree to our Terms & Privacy.</p>
<div class="clearfix">
<button type="button" class="cancelbtn">Cancel</button>
<button type="submit" class="signupbtn">Sign Up</button>
</div>
<img src="BF116-11KM.jpg" alt="Avatar" class="avatar">
</div>
</form>
<p id="log"></p>
</center>
</div>
<script>
function logSubmit(event)
{
var database = firebase.database();
function testResults(form)
{
var email = form.email.value;
var password = form.psw.value;
}
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function (error)
{
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
log.textContent = 'Sorry, Something went wrong. Please try again in a moment';
// ...
});
log.textContent = 'Signup Complete! Please login on the main page';
event.preventDefault();
}
const form = document.getElementById('form');
const log = document.getElementById('log');
form.addEventListener('submit', logSubmit);
</script>
Expected results would be the account appearing in my firebase console, but actual results include the "too many redirects" error.
Two notices:
your second input-element (password) never closes
how is the index.html supposed to support your form-submit?

Dropzone js validate on submit

I have a form where I am using dropzone.js for file upload. Now I am validating all the input fields. But i'm not able to validate the file before submission. If the file is uploaded, then the submission should work. Otherwise it should throw an error like - "please upload the file". How can i achieve this?
HTML code:
<form action="/action">
<div class="form-row">
<div class="form-group col-md-6">
<input type="text" class="form-control" id="first_name" name="first_name" placeholder="First Name" required>
</div>
<div class="form-group col-md-6">
<input type="text" class="form-control" id="last_name" name="last_name" placeholder="Last Name" required>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<textarea class="form-control" id="message" name="message" placeholder="Message"></textarea>
</div>
</div>
<div class="form-row">
<div id="resume" class="dropzone form-control"></div>
</div>
<input type="submit" class="btn btn-primary mt-10" id="item-submit" value="submit">
</form>
Javascript :
<script type="text/javascript">
$(document).ready(function () {
$("div#resume").dropzone({ url: "/change-this-later" });
var dropzone3;
Dropzone.autoDiscover = false;
dropzone3 = new Dropzone('#resume', {
maxFiles: 1,
});
$('#item-submit').click(function(e) {
e.preventDefault();
e.stopPropagation();
if ($('form#resume').valid()) {};
});
});
</script>
You can add a callback event which is called if the upload is successful
//indicates file upload is complete and is successful
var uploaded = false;
$("div#resume").dropzone({
url: "/change-this-later",
success: function (file, response) {
uploaded = true;
}
});
//Check the value of 'uploaded' when validating rest of fields
So I come around this. Since I submit all my images and fields in the same button, I just acceded to the files array in side the dropzone and validate that it's lenght wasn't 0. $animalImage is my dropzone.
var validateImages = function (animal) {
if ($animalImage.files.length == 0) {
swal({
title: 'Advertencia',
type: 'info',
html: "Debe de guardar al menos una imágen",
showCloseButton: true,
focusConfirm: false
});
return false;
}
return animal;
};
Hope it helps, side note a submit trough ajax so I just used dropzone for the user experience.

JavaScript form validation not working as intended

Good morning,
I'm working on some simple form validation. Whenever I submit my form, the error message appears, but I can repeatedly spam the button for numerous error messages. Is there a way I can change this to only show the error message once? I've also noticed that even if I populate both fields it will still flash quickly in my console with the error log but not show the error.
Can anyone tell me what I'm doing wrong here?
var uname = document.forms['signIn']['userame'].value;
var pword = document.forms['signIn']['password'].value;
function validateMe (e) {
if (uname.length || pword.length < 1 || '') {
var container = document.getElementById('error-container');
var errorMsg = document.createElement('div');
errorMsg.className = 'error-message';
errorMsg.innerHTML = '<span class="heading-large">Please enter a valid username or password</span>';
container.appendChild(errorMsg);
console.log('An error occured');
return false;
}
}
<form id="signIn" action='#'>
<div class="boxed left-floater">
<h1 class="heading-large margin-top">Sign in</h1>
<div id="error-container"></div>
<div class="form-group">
<label class="form-label-bold" for="username">Username</label>
<input class="form-control log-in-form-control" id="username" name="username" type="text">
</div>
<div class="form-group">
<label class="form-label-bold" for="password">Password</label>
<input class="form-control log-in-form-control" id="password" type="password" name="password">
</div>
<div>
<a class="right-floater forgotten-password" href="forgottenpassword.html">Forgotten Password</a>
<button class="button clear right-floater" type="submit" onclick="validateMe();">Sign In</button>
</div>
</div>
</form>
Fiddle
You must be clearing the contents of your container to avoid duplication of elements. Below are few things to note:
You were trying to get userame instead of username in your fiddle. May be spelling mistake.
Keep input type=submit instead of button
Pass the event to your validateMe function to prevent the default action of post.
Move the variables within the function to get the actual value all the time
function validateMe(e) {
e.preventDefault();
var uname = document.forms['signIn']['username'].value;
var pword = document.forms['signIn']['password'].value;
var container = document.getElementById('error-container');
container.innerHTML = ''; //Clear the contents instead of repeating it
if (uname.length < 1 || pword.length < 1) {
var errorMsg = document.createElement('div');
errorMsg.className = 'error-message';
errorMsg.innerHTML = '<span class="heading-large">Please enter a valid username or password</span>';
container.appendChild(errorMsg);
console.log('An error occured');
return false;
}
}
<form id="signIn" action='#'>
<div class="boxed left-floater">
<h1 class="heading-large margin-top">Sign in</h1>
<div id="error-container"></div>
<div class="form-group">
<label class="form-label-bold" for="username">Username</label>
<input class="form-control log-in-form-control" id="username" name="username" type="text">
</div>
<div class="form-group">
<label class="form-label-bold" for="password">Password</label>
<input class="form-control log-in-form-control" id="password" type="password" name="password">
</div>
<div>
<a class="right-floater forgotten-password" href="forgottenpassword.html">Forgotten Password</a>
<input value="Sign In" class="button clear right-floater" type="submit" onclick="validateMe(event);" />
</div>
</div>
</form>
Updated Fiddle
Edit - if condition was failing and have updated it accordingly
this is full work code
var uname = "";
var pword = "";
function validateMe(e) {
e.preventDefault();
uname = document.forms['signIn']['username'].value;
pword = document.forms['signIn']['password'].value;
if (uname.length || pword.length < 1 || '') {
var container = document.getElementById('error-container');
var errorMsg = document.createElement('div');
errorMsg.className = 'error-message';
errorMsg.innerHTML = '<span class="heading-large">Please enter a valid username or password</span>';
container.appendChild(errorMsg);
console.log('An error occured');
return false;
}
return true;
}
<form id="signIn">
<div class="boxed left-floater">
<h1 class="heading-large margin-top">Sign in</h1>
<div id="error-container"></div>
<div class="form-group">
<label class="form-label-bold" for="username">Username</label>
<input class="form-control log-in-form-control" id="username" name="username" type="text">
</div>
<div class="form-group">
<label class="form-label-bold" for="password">Password</label>
<input class="form-control log-in-form-control" id="password" type="password" name="password">
</div>
<div>
<a class="right-floater forgotten-password" href="forgottenpassword.html">Forgotten Password</a>
<button class="button clear right-floater" type="submit" onclick="validateMe(event);">Sign In</button>
</div>
</div>
</form>

How to use $asyncValidators with angularjs and set a warning message in the HTML

This is my first bigger form with validations and etc.
I've created a Registration form and I'm using ng-messages for validation. The problem is that I need to validate the username, does it already exist in the JSON server that we are using or it's available. Of course, if it's taken the warning pops out in the HTML where the username input is, if it's available the submit button is no more disabled (because the form will be $valid) and the user can register. I want to use angular-sanitize because I found this (I don't know if they are related):
ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
var value = modelValue || viewValue;
// Lookup user by username
return $http.get('/api/users/' + value).
then(function resolved() {
//username exists, this means validation fails
return $q.reject('exists');
}, function rejected() {
//username does not exist, therefore this validation passes
return true;
});
};
Here is the code I use now (reg form, controller and service):
// Controller:
export default class registerPageController {
constructor(userService, authenticationService, $location) {
this.register = "Register";
this.userService = userService;
this.$location = $location;
this.authenticationService = authenticationService;
this.hasLoggedIn = false;
}
onSubmit(user) {
let self = this;
let {
name,
age,
email,
username,
password
} = user;
self.userService.register(name, age, email, username, password).then((res) => {
self.userService.login(username, password).then(function (response) {
let data = response.data;
if (data.length) {
let user = data[0];
self.hasLoggedIn = true;
self.authenticationService.setCredentials(username, password);
self.$location.path('/');
}
});
})
.catch(err => {
// WHAT TO PUT HERE AFTER THE USERNAME EXIST VALIDATION ?
})
}
}
// Service:
export class UserService {
constructor($http) {
this.$http = $http;
}
login(username, password) {
return this.$http({
method: 'GET',
url: 'http://localhost:3000/users',
params: {
username: username,
password: password
}
});
}
register(name, age, email, username, password) {
return this.$http({
method: 'POST',
url: 'http://localhost:3000/users',
data: {
name: name,
age: age,
email: email,
username: username,
password: password
}
});
}
// SHOULD I PUT HERE THE USERNAME EXIST VALIDATION LOGIC ?
}
<div class="container main-content">
<form class="registrationForm" name="registerForm" ng-submit="register.onSubmit(register.user)" novalidate="novalidate">
<!-- Enter Name -->
<div class="form-group">
<label for="name" class="control-label"><span id="reqInfo">*</span> Name</label>
<input type="text" name="name" class="form-control" ng-model="register.user.name" ng-pattern="/[a-zA-Zа-яА-Я]+/" id="name"
required="" placeholder="Example: Petar Petrov">
<div ng-messages="registerForm.name.$error" ng-show="registerForm.name.$touched" style="color:maroon" role="alert">
<div ng-message="required">Your name is required</div>
</div>
</div>
<!-- User Age-->
<div class="form-group">
<label for="age" class="control-label"><span id="reqInfo">*</span> Age</label>
<input type="number" name="age" class="form-control" ng-model="register.user.age" ng-min="18" min="18" id="age" required=""
placeholder="Enter your age">
<div ng-messages="registerForm.age.$error" ng-show="registerForm.age.$touched" style="color:maroon" role="alert">
<div ng-message="min">You must be at leats 18 years old</div>
</div>
</div>
<!-- Enter E-mail -->
<div class="form-group">
<label for="email" class="control-label"><span id="reqInfo">*</span> E-mail</label>
<input type="email" name="email" class="form-control" ng-model="register.user.email" ng-pattern="/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+#)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+#)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%#\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/"
id="email" required="" placeholder="Example: mail#mail.net">
<div ng-messages="registerForm.email.$error" ng-show="registerForm.email.$touched" style="color:maroon" role="alert">
<div ng-message="required">Your valid e-mail is required</div>
</div>
<br>
<!-- Enter Username -->
<div class="form-group">
<label for="username" class="control-label"><span id="reqInfo">*</span> Username</label>
<input type="text" name="username" ng-minlength="5" ng-maxlength="20" class="form-control" ng-model="register.user.username"
ng-pattern="/^[A-Za-z0-9_]{1,32}$/" ng-minlength="7" id="username" required="" placeholder="Enter your username">
<div ng-messages="registerForm.username.$error" style="color:maroon" role="alert">
<div ng-message="minlength">Your Username must be between 7 and 20 characters long</div>
</div>
<br>
<!-- Enter Password -->
<div class="form-group">
<label for="password" class="control-label"><span id="reqInfo">*</span> Password</label>
<input type="password" name="password" class="form-control" ng-model="register.user.password" ng-minlength="7" id="password"
required="" placeholder="Enter your password">
<div ng-messages="registerForm.password.$error" style="color:maroon" role="alert">
<div ng-message="minlength">You Password must be at least 7 symbols long</div>
</div>
</div>
<!-- Register button -->
<div class="form-group">
<button class="btn btn-primary" type="submit" ng-disabled="!registerForm.name.$valid || !registerForm.age.$valid || !registerForm.email.$valid || !registerForm.username.$valid || !registerForm.password.$valid">Register</button>
</div>
<p>Fields with <span id="reqInfo">*</span> must be filled.</p>
</form>
</div>
Important is to know that I have being told explicitly to write it in ES6.
I have problem with the logic so look at my code and please fill it for me so I can use it and most important - learn it :S
Thank you so so much in advance!
I have implemented a directive for different kind of validations (sync Async), and it supports warning as well.
You may check it from
`https://plnkr.co/2WQHOo`
If this is what you needed and need more information, let me know I will try my best to answer.

Categories