Email validation in Vue.js - javascript

I have been working with Vue for 24 hours now, so forgive the ignorance. I have searched around and I'm getting close, but I'm sure it's my lack of understanding and basic principles.
I have a modal that opens when a button is clicked. This modal displays a form with an email input. I managed to get the modal working, but nothing happens when I type in an incorrect email.
Here's my code for the component:
<template>
<div>
<!-- Aside -->
<aside class="aside">
<button class="aside__btn button" #click="showModal = true">
Send Me The Tips
</button>
</aside>
<!-- Modal -->
<div class="modal" v-if="showModal">
<div class="modal-container">
<p class="modal__steps">Step 1 of 2</p>
<div class="relative">
<hr class="modal__divider" />
</div>
<div class="modal__heading-container">
<p class="modal__heading">Email Your Eail To Get <span class="modal__heading-span">Free</span>
</p>
<p class="modal__heading">iPhone Photography Email Tips:</p>
</div>
<form>
<input for="email" type="email" placeholder="Please enter your email here" required v-model="email">
<span class="floating-placeholder" v-if="msg.email">{{msg.email}}</span>
<!-- <span class="floating-placeholder">Please enter your email here</span> -->
<button class="modal__button button">Send Me The Tips</button>
</form>
</div>
</div>
</div>
</template>
<script>
export default ({
data () {
return {
showModal: false,
email: '',
msg: [],
}
},
watch: {
email(value) {
// binding this to the data value in the email input
this.email = value;
this.validateEmail(value);
}
},
methods: {
validateEmail(value){
if (/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(value))
{
this.msg['email'] = '';
} else{
this.msg['email'] = 'Please enter a valid email address';
}
}
}
})
</script>
I'm using Laravel if that's of importance.

I would delete the watch and add an event listener on blur like so:
<input for="email" type="email" placeholder="Please enter your email here" required v-model="email" #blur="validateEmail" >
and update the validateEmail method like so :
validateEmail() {
if (/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(this.email)) {
this.msg['email'] = 'Please enter a valid email address';
} else {
this.msg['email'] = '';
}
}
You could also change the event listener to change #change if it serves your needs better.

You could also checkout Vuelidate which handles form validation. For example:
<template>
<div>
<input
class="rounded shadow-sm border border-warning"
v-model="form.email"
placeholder="E-mail"
#input="$v.form.email.$touch"
:state="$v.form.email.$dirty ? !$v.form.email.$error : null" />
</div>
</template>
<script>
import {required, email} from "vuelidate/lib/validators";
export default {
data() {
return {
form: {
email: null,
}
};
},
validations: {
form: {
email: {
required,
email
}
}
},
};
</script>

Related

I am attempting to create a firebase login page on a web app, however when I attempt to login, nothing happens [duplicate]

I'm trying to get the sign in part working on my webapp but it's not working properly.
Whenever I press the login button the page either refreshes and the url gets updated with the credentials and stays at the same page OR the router gets pushed and goes to the 'homepage' without logging the user in.
I also followed this guide for reference: https://blog.logrocket.com/vue-firebase-authentication/
What's weird is that the sign up part is working just fine.
SignIn.vue
<div class="card-body">
<form>
<!-- email -->
<div class="input-group form-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-user"></i></span>
</div>
<input id="email" type="email" class="form-control" name="email" placeholder="e-mail" value required autofocus v-model="form.email" />
</div>
<!-- password -->
<div class="input-group form-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-key"></i></span>
</div>
<input id="password" type="password" class="form-control" name="password" placeholder="password" required v-model="form.password" />
</div>
<!-- error -->
<div v-if="error" class="alert alert-danger animated shake">{{ error }}</div>
<br />
<!-- login -->
<div class="form-group d-flex justify-content-between">
<div class="row align-items-center remember"><input type="checkbox" v-model="form.rememberMe" />Remember Me</div>
<input type="submit" #click="submit" value="Login" class="btn float-right login_btn" />
</div>
</form>
</div>
Script in SignIn.vue
<script>
import firebase from 'firebase';
export default {
data() {
return {
form: {
email: '',
password: '',
rememberMe: false
},
error: null
};
},
methods: {
submit() {
firebase
.auth()
.signInWithEmailAndPassword(this.form.email, this.form.password)
.catch(err => {
this.error = err.message;
})
.then(data => {
this.$router.push({ name: 'home' });
});
}
}
};
</script>
Store.js
import Vue from 'vue';
import Vuex from 'vuex';
import profile from './modules/profile';
import authenticate from './modules/authenticate';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
profile,
authenticate
}
});
Authenticate.js in store
const state = {
user: {
loggedIn: false,
data: null
}
};
const getters = {
user(state) {
return state.user;
}
};
const mutations = {
SET_LOGGED_IN(state, value) {
state.user.loggedIn = value;
},
SET_USER(state, data) {
state.user.data = data;
}
};
const actions = {
fetchUser({ commit }, user) {
commit('SET_LOGGED_IN', user !== null);
if (user) {
commit('SET_USER', {
displayName: user.displayName,
email: user.email
});
} else {
commit('SET_USER', null);
}
}
};
export default {
state,
mutations,
actions,
getters
};
It is probably because you assign the submit type to your button, your form is submitted before the Firebase method is triggered.
You should change the button code from
<input type="submit" #click="submit" value="Login" class="btn float-right login_btn" />
to
<input type="button" #click="submit" value="Login" class="btn float-right login_btn" />
See the W3 specification for more detail on button types.

How to catch the invalid response from the backend and display that error as alert in UI page in vue.js?

i am developing one registration page and it's connected with the backend API by using axios package it's working fine ,if i enter invalid credentials or already existing emailID it's showing me user registered successfully as alert and from the response i am getting [invalid response 422]1(status as 422 when i am giving existing user credentials and at that time also it's showing user registered successfully as alert [like this it's showing]2), i want to catch the response or status from the backend and placed inside catch block which is present inside the Register.vue component and display as a alert message(for invalid response also), please help me to fix this issue on valid response only it's should display success msg and if it's invalid means it's should display the error as alert based on response msg (if response==422 means then i want to print invalid as alert)
Register.vue
<template>
<div class="main">
<div class="container">
<img src="../assets/sideImg.png" alt="notFound" />
<p>Online Book Shopping</p>
<div class="box">
<div class="headings">
<h5 class="signin">Login</h5>
<h5 class="signup">signup</h5>
</div>
<form ref="myForm" #submit.prevent="handlesubmit">
<div class="fullname">
<p>FullName</p>
<input type="name" class="namebox" required v-model="fullName" autocomplete="off" pattern="[A-Za-z]{3,12}">
</div>
<div class="username">
<p>EmailID</p>
<input type="email" class="emailbox" required v-model="emailID" pattern="^[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$">
</div>
<div class="pass">
<p>Password</p>
<input :type="password_type" class="password" id="passField" v-model="password" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$!%*?&])[A-Za-z\d#$!%*?&]{6,}$" required>
<i class="bi bi-eye-slash" id="togglePassword" #click="togglePassword();"></i>
</div>
<div class="mobile">
<p>MobileNumber</p>
<input type="tel" class="telephone" v-model="mobile" pattern="^\d{10}$" required>
</div>
<button class="btn-section" type="submit">Signup</button>
</form>
</div>
</div>
</div>
</template>
<script>
import service from '../service/User'
export default {
name: 'Register',
data() {
return {
fullName: '',
emailID: '',
password: '',
mobile: '',
password_type: "password",
}
},
methods: {
togglePassword() {
this.password_type = this.password_type === 'password' ? 'text' : 'password'
document.getElementById('passField').style.margin='0px 0px 0px 69px';
document.getElementById('passField').style.width="252px";
document.getElementById('passField').style.height="35px";
document.getElementById('passField').style.background="$pale_white 0% 0% no-repeat padding-box";
},
handlesubmit() {
let userData = {
fullName: this.fullName,
emailID: this.emailID,
password: this.password,
mobile: this.mobile
}
service.userRegister(userData).then(response => {
alert("user registered successfully");
this.$refs.myForm.reset();
return response;
}).catch(error => {
if(error.response==422){alert("internal server issue");}
return error;
})
}
}
}
</script>
<style lang="scss" scoped>
#import "#/styles/Register.scss";
</style>
axios.js[responsible for postData]
import axios from 'axios'
axios.defaults.baseURL=process.env.VUE_APP_AXIOS_URL
axios.defaults.headers.common['Authorization']='Bearer'+ localStorage.getItem('token');
export default class AxiosService{
postData(url,data){
return axios.post(url,data).then(response =>{
return response;
}).catch(error=>{
return error;
})
}
}
User.js[responsible for hitting backend api]
import AxiosService from '../service/axios';
const axios=new AxiosService()
export default{
userRegister(data){
return axios.postData("/register",data);
},
}

Why when the accept terms checkbox is not checked or the gender is not chosen then also my email shows up as incorrect?

I am creating a sign up to newsletter form and my problem is that when my accept terms is not checked or one of the gender radio buttons is not selected then also my email is not validated even though they work on independent variables. When I type in the email, choose gender and check the terms I get 'success' in console as expected. Then with the same email when I uncheck the terms it shows both terms and email as invalid, same happens when no gender is chosen. I am writing this using vue.js
Template
<form action="">
<input type="email" #focus="showRestOfForm = true, invalidEmail = false" placeholder="Enter your email" class="email"
v-model="email" :class="{invalidEmail: invalidEmail}">
<p v-if="invalidEmail" class="invalid-message">Incorrect Email Format</p>
<!-- Animation for showing the rest of newsletter form -->
<transition name="rest">
<div class="rest-of-form" v-if="showRestOfForm">
<div class="gender-selection" :class="{invalid: invalidGender}" #click="invalidGender = false">
<div class="gender-select">
<input type="radio" name="gender" value="man" v-model="gender">
<div class="custom-radio"></div>
<label for="man">man</label>
</div>
<div class="gender-select">
<input type="radio" name="gender" value="woman" v-model="gender">
<div class="custom-radio"></div>
<label for="woman" class="woman-label">woman</label>
</div>
</div>
<p class="invalid-message" v-if="invalidGender">Please select your gender</p>
<div class="terms" :class="{invalid: invalidTerms}">
<input type="checkbox" id="terms" v-model="terms" #click="invalidTerms = false">
<label for="terms">Accept Terms and Regulations</label>
</div>
<p class="invalid-message" v-if="invalidTerms">Please accept the terms and regulations</p>
<button class="sign-up" #click.prevent="signUp">Sign Up</button>
</div>
</transition>
</form>
Script
methods: {
signUp() {
// Validating email using a regular expression using RFC2822 reg expresssion validation
// let emailValid
const emailRegExp = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/g
if(emailRegExp.test(this.email) && this.gender && this.terms){
console.log("success")
}else{
if(!emailRegExp.test(this.email)){
this.invalidEmail = true
}
if(!this.gender){
this.invalidGender = true
}
if(!this.terms){
this.invalidTerms = true
}
}
}
}
Scss
.invalidEmail{
border: 0.1rem solid red;
color: red;
}
.invalid-message{
color: red;
}
.invalid{
color: red;
}
Saw your comments. This is a weird one.
I built a test component based on your code in my Vue 2 sandbox app.
<template>
<div class="email-validation">
<h3>EmailValidation.vue</h3>
<div class="row">
<div class="col-md-6">
<form>
<input type="email" #focus="showRestOfForm = true, invalidEmail = false" placeholder="Enter your email"
class="email" v-model="email" :class="{invalidEmail: invalidEmail}">
<p v-if="invalidEmail" class="invalid-message">Incorrect Email Format</p>
<!-- Animation for showing the rest of newsletter form -->
<transition name="rest">
<div class="rest-of-form" v-if="showRestOfForm">
<div class="gender-selection" :class="{invalid: invalidGender}" #click="invalidGender = false">
<div class="gender-select">
<input type="radio" name="gender" value="man" v-model="gender">
<div class="custom-radio"></div>
<label for="man">man</label>
</div>
<div class="gender-select">
<input type="radio" name="gender" value="woman" v-model="gender">
<div class="custom-radio"></div>
<label for="woman" class="woman-label">woman</label>
</div>
</div>
<p class="invalid-message" v-if="invalidGender">Please select your gender</p>
<div class="terms" :class="{invalid: invalidTerms}">
<input type="checkbox" id="terms" v-model="terms" #click="invalidTerms = false">
<label for="terms">Accept Terms and Regulations</label>
</div>
<p class="invalid-message" v-if="invalidTerms">Please accept the terms and regulations</p>
<button class="sign-up" #click.prevent="signUp">Sign Up</button>
</div>
</transition>
</form>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
showRestOfForm: false,
email: '',
gender: null,
invalidEmail: false,
invalidTerms: false,
invalidGender: false,
terms: false
}
},
methods: {
signUp() {
// Validating email using a regular expression using RFC2822 reg expresssion validation
// let emailValid
const emailRegExp = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/g
if (emailRegExp.test(this.email) && this.gender && this.terms) {
console.log("success")
}
else {
console.log('entered else block')
if ( !(emailRegExp.test(this.email)) ) {
console.log('this.email')
console.log(this.email);
console.log('regex test result')
console.log(emailRegExp.test(this.email))
console.log('not regex test result')
console.log(!emailRegExp.test(this.email))
console.log('setting email invalid')
this.invalidEmail = true
}
if (!this.gender) {
this.invalidGender = true
}
if (!this.terms) {
this.invalidTerms = true
}
}
}
}
}
</script>
<style scoped>
.invalidEmail {
border: 0.1rem solid red;
color: red;
}
.invalid-message {
color: red;
}
.invalid {
color: red;
}
</style>
Notice the logging that I added to the email test in 'signUp()'.
When I run the app as you said with a valid email address but no gender or terms, I am getting the same error you describe.
Then when I look at the logging in my console, I see this:
Here you can see that both 'regex test result' and 'not regex test result' are returning 'true'.
So at this point I think you have a problem with your regex implementation. I'm not regex expert, but I did some searching and found the JS RegExp constructor.
I suggest simplying your regular expression, and possibly using the RegExp constructor, in order to see if you can get it working.
I found this simplified email regex, and it works now:
const emailRegExp = /^.+#.+\..+$/

Nuxt / Netlify Form returning empty form data fields

I'm using Nuxt and Netlify Forms for a contact form, Everything is working as expected (validation, submit success) however I am getting empty form fields on submissions. I have tried matching the v-model and form names with no success. Do I have to change the body.encode to retrieve the v-model fields or somehow get the value of the name fields inputs?
Markup:
<form
name="contactForm"
method="post"
netlify-honeypot="bot-field"
data-netlify="true"
#submit.prevent="handleSubmit()"
>
<input type="hidden" name="form-name" value="contactForm" />
<div class="form-group">
<!--user name -->
<div class="floating-label">
<input
v-model="contact_name"
class="floating-input"
name="name"
type="text"
placeholder=" "
:class="{
'child-has-error': $v.contact_name.$error,
}"
/>
<label>Enter Your Name</label>
<p v-if="$v.contact_name.$dirty">
<span
v-if="!$v.contact_name.required"
class="form__alert"
>
Name is required
</span>
</p>
</div>
<!-- end user name -->
<!--user email -->
<div class="floating-label">
<input
v-model="contact_email"
class="floating-input"
type="text"
name="email"
placeholder=" "
:class="{
'child-has-error': $v.contact_email.$error,
}"
/>
<label>Enter Your Email</label>
<p v-if="$v.contact_email.$dirty">
<span
v-if="!$v.contact_email.required"
class="form__alert"
>
Email is required
</span>
<span v-if="!$v.contact_email.email" class="form__alert">
Please enter a valid email
</span>
</p>
</div>
<!-- end user email -->
<!--user message -->
<div class="floating-label">
<textarea
v-model="contact_message"
class="form-control form-control--textarea"
rows="5"
name="message"
placeholder="Enter Your Message"
:class="{ 'child-has-error': $v.contact_message.$error }"
/>
<p v-if="$v.contact_message.$dirty">
<span
v-if="!$v.contact_message.required"
class="form__alert"
>
Enter Your Message
</span>
<span
v-if="!$v.contact_message.minLength"
class="form__alert"
>
Message must be over 10 characters :)
</span>
</p>
</div>
<!-- end user message -->
</div>
<button type="submit" class="btn btn-primary">
Send Message
<font-awesome-icon far icon="arrow-right" />
</button>
</form>
Script:
<script>
import { required, email, minLength } from 'vuelidate/lib/validators'
export default {
data() {
return {
title: 'Contact Form',
show_contact: true,
contact_name: '',
contact_email: '',
contact_message: '',
form: {
name: '',
email: '',
message: '',
},
}
},
validations: {
contact_name: {
required,
},
contact_email: {
required,
email,
},
contact_message: {
required,
minLength: minLength(10),
},
},
methods: {
encode(data) {
return Object.keys(data)
.map(
(key) => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`
)
.join('&')
},
handleSubmit() {
this.$v.$touch()
if (this.$v.$invalid) {
return true
}
fetch('/', {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: this.encode({
'form-name': 'contactForm',
...this.form,
}),
})
// eslint-disable-next-line no-console
.then(() => {
this.show_contact = false
// eslint-disable-next-line no-console
console.log('Message Success')
})
// eslint-disable-next-line no-console
.catch((e) => console.error(e))
},
},
}
</script>
You've been sending this.form as your data
body: this.encode({
'form-name': 'contactForm',
...this.form,
}),
but you never set values to it based on your inputs. I did not see any reference to it.
Either use those in your v-model bindings or convert this.form from data to a computed property like:
form() {
return {
name: this.contact_name,
email: this.contact_email,
message: this.contact_message
}
}
I'm working on a Nuxt/Netlify project too currently.
There are 3 scenarios
If you're using Nuxt as a static site
It looks like you're not binding your form values to the fields you're sending to Netlify
It's probably safe to replace
form: {
name: '',
email: '',
message: '',
},
with
form: {
contact_name: '',
contact_email: '',
contact_message: '',
}
Otherwise, assuming you're using Nuxt as an SPA and using a static stand-in form in this example here
Your stand-in form must contain fields with the same name as your actual form field. Otherwise, your form will be submitted but won't be seen on the NetlifyUI due to their build bots not expecting those form fields.

Show bootstrap alert with condition (Vue.js): how can I access this variable in order to change its value?

First of all I would like to apologize if the answer to my question is obvious, however since I'm still pretty new to Vue.js, I'm getting really stuck here and I need help.
I got an authentication system and if the user wants to register without putting in an username, I would like to show an bootstrap alert. The code looks like this right now:
<template>
<div class="container">
<div class="row">
<div class="col-md-6 mt-5 mx-auto">
<form v-on:submit.prevent="register">
<h1 class="h3 mb-3 font-weight-normal">Register</h1>
<div class="form-group">
<label for="username">Username</label>
<input
type="text"
v-model="username"
class="form-control"
name="username"
placeholder="Please choose your username"
>
</div>
<div class="form-group">
<label for="email">Email Address</label>
<input
type="email"
v-model="email"
class="form-control"
name="email"
placeholder="Please enter your email address"
>
</div>
<div class="form-group">
<label for="password">Password</label>
<input
type="password"
v-model="password"
class="form-control"
name="password"
placeholder="Please choose your password"
>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Register</button>
</form>
<div>
<b-alert variant="success" show>Example alert</b-alert>
</div>
<div>
<b-alert variant="danger" :show="showAlert">Example Alert!</b-alert>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
import router from "../router";
export default {
data() {
return {
username: "",
email: "",
password: "",
showAlert: false };
},
methods: {
register() {
axios
.post("/user/register", {
username: this.username,
email: this.email,
password: this.password
})
.then(res => {
if (!res.data.username) {
// show an alert, I would like to do something similar to "showAlert = true;"
} else {
// redirect to login
}
})
.catch(err => {
console.log(err);
});
}
}
};
</script>
<style scoped>
#import "../assets/css/reglog.css";
#import "../assets/css/modal.css";
</style>
However I'm not sure how to access the showAlert variable neither how to change its value in the if-statement. The only thing that I know here is that if I change the showAlert manually in the code (line 9 counting from the script tag) from false to true, the page does react and shows the alert when wanted.
I'm sorry if you need more information or if something is unclear, I'm a bit tired and stuck with this for some hours, not gonna lie.
You can access showAlert variable following: this.showAlert = true
.then(res => {
if (!res.data.username) {
this.showAlert = true; // update showAlert
} else {
// redirect to login
}
})

Categories