I have created a Javascript form validator.
What I would like to do if if all the fields are valid, I would like to be able to submit the form.
I am checking the validity of the fields both on entry and onSubmit.
My thoughts are to use an onClick handler.
For example:
document.getElementById("submit-button").addEventListener("click", submitForm);
submitForm(e) {
e.preventDefault();
form.submit();}
But I am unsure on the best way to implement this with the below validator. For example, should this be used outside of the class validator or within it?
Here is my validator code:
class FormValidator {
constructor(form, fields) {
this.form = form;
this.fields = fields;
}
initialize() {
this.validateOnEntry();
this.validateOnSubmit();
}
validateOnSubmit() {
let self = this;
this.form.addEventListener("submit", (e) => {
e.preventDefault();
self.fields.forEach((field) => {
const input = document.querySelector(`#${field}`);
self.validateFields(input);
});
});
}
validateOnEntry() {
let self = this;
this.fields.forEach((field) => {
const input = document.querySelector(`#${field}`);
input.addEventListener("input", (event) => {
self.validateFields(input);
});
});
}
validateFields(field) {
// Check presence of values
if (field.value.trim() === "") {
this.setStatus(
field,
`${field.previousElementSibling.innerText} cannot be blank`,
"error"
);
} else {
this.setStatus(field, null, "success");
}
// check for a valid email address
if (field.type === "email") {
const re = /\S+#\S+\.\S+/;
if (re.test(field.value)) {
this.setStatus(field, null, "success");
} else {
console.log("ERROR", field.value);
this.setStatus(field, "Please enter valid email address!", "error");
}
}
// Check for valid password
if (field.id === "password") {
if (field.value.trim() == "") {
this.setStatus(field, "Password required!", "error");
} else if (field.value.length <= 10) {
this.setStatus(field, "Password too short!", "error");
} else if (field.value.length >= 50) {
this.setStatus(field, "Password too long!", "error");
} else {
this.setStatus(field, null, "success");
}
}
console.log("We're valid");
}
setStatus(field, message, status) {
const successIcon = field.parentElement.querySelector(".icon-success");
const errorIcon = field.parentElement.querySelector(".icon-error");
const errorMessage = field.parentElement.querySelector(".error-message");
if (status === "success") {
if (errorIcon) {
errorIcon.classList.add("hidden");
}
if (errorMessage) {
errorMessage.innerText = "";
}
successIcon.classList.remove("hidden");
field.classList.remove("input-error");
}
if (status === "error") {
if (successIcon) {
successIcon.classList.add("hidden");
}
field.parentElement.querySelector(".error-message").innerText = message;
errorIcon.classList.remove("hidden");
}
}
}
const form = document.querySelector(".form");
const fields = ["email", "password"];
const validator = new FormValidator(form, fields);
validator.initialize();
Related
the problem is, I am not able to make a request to MongoDB after validating the request with the following code:
module.exports.validateRegisterInput = (
username,
email,
password,
confirmPassword
) => {
const errors = {};
if (username.trim() === "") {
errors.username = "Username must be provided";
}
if (email.trim() === "") {
errors.email = "Email must be provided";
} else {
const validEmail =
/^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*#([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/;
if (!email.match(validEmail)) {
errors.email = "Email must be valid";
}
}
if (password === "") {
errors.password = "Password must be provided";
}
if (password !== confirmPassword) {
errors.password = "Passwords must match";
}
return {
errors,
vaild: Object.keys(errors).length < 1,
};
};
the validators work fine and check the request for any mistakes but once there is no issue with the request it does not let me send a request and raises an error anyway, also I am using the validators in the following way:
module.exports = {
Mutation: {
async register(
parent,
{ registerInput: { username, email, password, confirmPassword } }
) {
const { valid, errors } = validateRegisterInput(
username,
email,
password,
confirmPassword
);
if (!valid) {
throw new UserInputError("Errors", { errors });
}
...
so, I solved the problem, the problem was I was not calling the question directly and changed it to:
validateRegisterInput(username, email, password, confirmPassword);
and add errors in the validators and not in the index
const { UserInputError } = require("apollo-server");
module.exports.validateRegisterInput = (
username,
email,
password,
confirmPassword
) => {
if (username.trim() === "") {
throw new UserInputError("Username must be provided", {
errors: {
username: "Username must be provided",
},
});
}
if (email.trim() === "") {
throw new UserInputError("Email must be provided", {
errors: {
email: "Email must be provided",
},
});
} else {
const validEmail =
/^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*#([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/;
if (!email.match(validEmail)) {
throw new UserInputError("Email must be correct", {
errors: {
email: "Email must be correct",
},
});
}
}
if (password === "") {
throw new UserInputError("Password must be provided", {
errors: {
password: "Password must be provided",
},
});
}
if (password !== confirmPassword) {
throw new UserInputError("Passwords must match", {
errors: {
password: "Password must match",
},
});
}
};
that's my connect page's form. it works great. but i want to validate in validation function line (validate() ) ,too. however, it is sending mail even though empty inputs.
i think, i have to add something in handleSubmit line with isValid line.
what should I do?
const initialState={
name: "",
subject: "",
email: "",
message: "",
sent:false,
nameError: "",
}
export default class Validation extends React.Component {
state = initialState;
handleName = (e) => {
this.setState({
name:e.target.value
})
}
validate = () => {
let nameError= "";
if (!this.state.name) {
nameError = "Name cannot be blank!"
}
if (nameError) {
this.setState({ nameError });
return false;
}
return true;
}
handleSubmit = (e) => {
e.preventDefault();
const isValid = this.validate();
if (isValid) {
console.log(this.state);
}
this.sendingMail();
}
sendingMail=()=>{
let data = {
name:this.state.name,
}
axios.post('http://localhost:3001/api/form',data)
.then(res=>{
this.setState({
sent:true,
},this.resetForm())
})
.catch(()=> {
console.log('message not sent');
})
}
I have written three files which are: home-flatfull.jsp, settings-social-prefs.html and
google-js-api-wrapper.js files.
In home-flatfull.jsp file, I have written as below:
head.js('jscore/lib/base64.js', 'jscore/lib/google-js-api.js', 'jscore/lib/google-js-api-wrapper.js', function () {
var config = {
apiKey: 'AIzaSyCa52K8J68kr5b4S7Afu1FQzeleCfvzOFs',
clientId: '492662354647-877atvgj1a0pu82nrutsm50rcmg0lufh.apps.googleusercontent.com',
discoveryDocs: ["https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"],
scopes: 'https://www.googleapis.com/auth/gmail.readonly',
listener: function(response){
console.log(' Check google ');
console.log(response);
}
};
googleJSAPI = GoogleJSAPI.getInstance(config);
});
In settings-social-prefs.html file I have defined as below:
<a onclick="googleJSAPI.signIn()" class="btn btn-sm btn-default">
{{agile_lng_translate 'prefs-email' 'enable'}}
</a>
In google-js-api-wrapper.js file, I have defined as below:
class GoogleJSAPI {
emailRegx = /^(([^<>()[\]\\.,;:\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,}))$/;
instance;
isActive = false;
constructor(config) {
console.log(' google code loaded ');
gapi.load('client:auth2', () => {
gapi.client.init({
apiKey: config.apiKey,
clientId: config.clientId,
discoveryDocs: config.discoveryDocs,
scope: config.scopes
}).then(() => {
this.isActive = true;
console.log(' config loaded ');
gapi.auth2.getAuthInstance().isSignedIn.listen(config.listener);
}, (error) => {
this.isActive = false;
console.log(JSON.stringify(error, null, 2));
});
});
}
static getInstance(config) {
if (!this.instance) {
this.instance = new GoogleJSAPI(config);
}
return this.instance;
}
isActive() {
return this.isActive;
}
isUserLoggedIn() {
return gapi.auth2.getAuthInstance().isSignedIn.get();
}
signIn = () => {
gapi.auth2.getAuthInstance().signIn();
}
signOut() {
gapi.auth2.getAuthInstance().signOut();
}
getSorted(a, b) {
return new Date(b.date).getTime() - new Date(a.date).getTime();
}
getMailList(queryObject) {
return new Promise((resolve, reject) => {
gapi.client.gmail.users.messages.list(queryObject).then(function (response) {
resolve(response.result);
});
});
}
getMailContentById(id) {
return new Promise((resolve, reject) => {
gapi.client.gmail.users.messages.get({
'userId': 'me', 'id': id
}).then((response) => {
let message = {};
let headers = response.result.payload.headers;
headers.forEach((header) => {
if (header.name === "From") {
message['from'] = header.value;
} else if (header.name === "Subject") {
message['subject'] = header.value;
} else if (header.name === "To") {
message['to'] = theader.value;
} else if (header.name === "Date") {
message['date'] = header.value;
} else if (header.name === "Cc") {
message['cc'] = header.value;
}
});
try {
if (response.result.payload) {
let body = "";
if (response.result.payload.body.size > 0) {
body = response.result.payload.body.data;
} else {
let bodyParts = response.result.payload.parts;
bodyParts.forEach((part, index) => {
if (part.type = "text/html") {
//console.log(index);
body = part.body.data;
return;
}
});
}
message['message'] = Base64.decode(body);
// console.log(message['body']);
}
} catch (e) {
//console.log(index);
//console.log(response.result);
//console.log(e);
}
resolve(message);
});
});
}
getInboxMailsWithContent(nextPageToken, fromEmail) {
var qData = '';
var queryObject = {
'userId': 'me',
'labelIds': ['INBOX']
};
if (nextPageToken) {
queryObject['pageToken'] = nextPageToken;
}
if (fromEmail) {
qData += 'from:' + fromEmail;
}
queryObject['q'] = qData;
return new Promise((resolve, reject) => {
gapi.client.gmail.users.messages.list(queryObject).then((response) => {
let resultObject = {
nextPageToken: response.result.nextPageToken
};
let messages = new Array();
let rawMessages = response.result.messages;
rawMessages.forEach((rawMessage, index) => {
gapi.client.gmail.users.messages.get({
'userId': 'me', 'id': rawMessage.id
}).then((response) => {
let message = {
id: rawMessage.id
};
let headers = response.result.payload.headers;
headers.forEach((header) => {
if (header.name === "From") {
message['from'] = header.value;
} else if (header.name === "Subject") {
message['subject'] = header.value;
} else if (header.name === "To") {
message['to'] = header.value;
} else if (header.name === "Date") {
message['date'] = header.value;
} else if (header.name === "Cc") {
message['cc'] = header.value;
}
});
try {
if (response.result.payload) {
let body = "";
if (response.result.payload.body.size > 0) {
body = response.result.payload.body.data;
} else {
let bodyParts = response.result.payload.parts;
bodyParts.forEach((part, index) => {
if (part.type = "text/html") {
f //console.log(index);
body = part.body.data;
return;
}
});
}
message['message'] = Base64.decode(body);
// console.log(message['body']);
}
} catch (e) {
//console.log(index);
//console.log(response.result);
//console.log(e);
}
messages[index] = message;
});
});
// resultObject.messages = messages.sort(this.getSorted);
resultObject.messages = messages;
resolve(resultObject);
});
});
}
}
function getInboxMailsWithContent(nextPageToken, fromEmail, callback) {
googleJSAPI.getInboxMailsWithContent(nextPageToken, fromEmail).then((response) => {
setTimeout(() => {
if (callback && typeof (callback) == "function") {
callback(response);
}
}, 3000);
});
}
When I clicked on enable button in settings-social-prefs.html file, I am just getting the gmail login page and gmail password page once I have provided gmail username and password, I got the consent screen which asks to allow access to user's email then I am getting the blank screen without getting the Gmail Read-Only mails of a specified user who has logged in. Can you please help me on this to get Gmail Read-Only mails when I click on enable button.
you may turn off two factor authentication (if on) and also "allow low secure apps to connect" in google my account settings
Ps: Displaying API in public should be avoided :-)
I wanted to retrieve an information from backend if some email address from input already exists. Based on this information I'm calling a function that make a post that inserts user into database. The problem is that user is inserted only after second click on my SignUp button (function registerUser is called on this button).
Component stuff:
registerUser(form: NgForm) {
let date: Date = new Date();
this.newUser.registrationDate = date;
this.checkEmailStatus(); //IMPLEMENTATION BELOW
if (this.signupForm.valid === true && this.emailStatus) {
this.portfolioAppService.registerUser(this.newUser).subscribe((data) => {
this.clearFields();
this.navigateToLogin();
},
error => console.error(error)
);
}
}
checkEmailStatus() {
this.portfolioAppService.checkEmailStatus(this.newUser.email).subscribe((data: string) => {
if (data != "") {
this.emailStatus = true;
}
else this.emailStatus = false;
},
error => console.error(error)
);
}
Here is my service:
checkEmailStatus(email: string): Observable<string> {
return this.http.get<string>(`/api/Users/CheckEmailStatus_${email}`, this.httpOptions);
}
Here is backend:
[HttpGet]
[Route("~/api/Users/CheckEmailStatus_{email}")]
public string CheckEmailStatus(string email)
{
try
{
User user = _context.Users.Where(u => u.Email == email).FirstOrDefault();
if (user != null)
{
return user.Email;
}
else
{
return "";
}
}
catch (Exception e)
{
throw new Exception("Error!");
}
}
Call to this.portfolioAppService.checkEmailStatus() is asynchronous. So when you check if (this.signupForm.valid === true && this.emailStatus) after the this.checkEmailStatus() call, the variable this.emailStatus is still undefined. To fix it, you could return an observable from the checkEmailStatus() in the component. Try the following
Component
registerUser(form: NgForm) {
let date: Date = new Date();
this.newUser.registrationDate = date;
this.checkEmailStatus().pipe(take(1)).subscribe(status => {
if (this.signupForm.valid === true && status) { // <-- check the status of email address
this.portfolioAppService.registerUser(this.newUser).subscribe((data) => {
this.clearFields();
this.navigateToLogin();
},
error => console.error(error)
);
}
});
}
checkEmailStatus() : Observable<boolean> {
const result = new Subject<boolean>();
this.portfolioAppService.checkEmailStatus(this.newUser.email).subscribe(
(data: string) => {
if (data !== '') {
result.next(true);
}
else result.next(false);
},
error => {
console.error(error);
result.next(false);
}
);
return result.asObservable();
}
My problem is to add data to the database by taking the information from a form.
I want to add the information as "name". I can add "email" correctly but not other data.
My code:
buttonsignup.addEventListener('click', error => {
var nameCompany = document.getElementById('nameCompany').value;
var email = document.getElementById('email').value;
});
function add(nameCompany,email) {
firebase.database().ref().child('users_company').push({
nameCompany: nameCompany,
email: email
});
}
function intFirebase () {
/*CURRENT USER*/
firebase.auth().onAuthStateChanged(function(user) {
if (user != null) {
console.log(user);
console.log('El UID es '+user.uid);
add(nameCompany,user.email);
} else {
console.log('No user is signed in.');
}
});
}
window.onload = function() {
intFirebase();
}
Okay, After turning the coffee into code. I found this solution. But ... Is it a good practice?
const database = firebase.database();
var user = firebase.auth().currentUser;
/* BOTON SIGNUP */
buttonsignup.addEventListener('click', error => {
var nameCompany = document.getElementById('nameCompany').value;
var email = document.getElementById('email').value;
var password_1 = document.getElementById('password_1').value;
var password_2 = document.getElementById('password_2').value;
if (password_1 == password_2) {
if (password_1.length < 8) {
console.log('ContraseƱa muy corta');
document.getElementById("errorPassword").innerHTML = "8 characters";
} else {
firebase.auth().createUserWithEmailAndPassword(email, password_1).then (function(result) {
add(nameCompany,email);
}).catch(function (error) {
var errorCode = error.code;
var errorMessage = error.message;
};
});
}
} else{
console.log('errorPassword');
}
});
function add(nameCompany,email) {
firebase.database().ref().child('users_company').push({
nameCompany: nameCompany,
emailCompany: email
});
}
function intFirebase () {
/*CURRENT USER*/
firebase.auth().onAuthStateChanged(function(user) {
if (user != null) {
console.log(user);
console.log('El UID es '+user.uid);
} else {
console.log('No user is signed in.');
}
});
}
window.onload = function() {
intFirebase();
}
And database rules
{
"rules": {
"users_company": {
"$uid": {
".read": "auth != null && auth.uid === $uid",
".write": true,
//Change this code to: I can not do scripts in the database. -> ".write": "auth != null && auth.uid === $uid",
"nameCompany" : {
".validate": "newData.isString() && newData.val().length < 100"
},
"emailCompany" :{
".validate": "newData.isString() && newData.val().length < 100"
}
}
}
}
}
In your intFirebase function you are only calling your database if there is a current user already logged in. The reason your email is working, is only because you are using 'user.email,' after it sees that a user is indeed logged in.
If you are trying to create a new user (which I think that is what your event listener at the top is trying to do), then you should move your add function to fire off when you submit the form.