I have a form where the user has to enter a field value:
<template>
<div class="authentication-template">
<div class="authentication-template__inner">
<div class="authentication-template__content">
<div class="authentication-template__form-stage">
Этап 1 из 3
</div>
<h2>{{ title }}</h2>
<form #submit.prevent="submitHandler" class="authentication-template__form" action="">
<div class="authentication-template__form-item">
<p>Номер телефона</p>
<input
type="text"
placeholder="+7(921)123-45-67"
maxlength="16"
:class="$v.phone.$error ? 'invalid' : ''"
v-model.trim="phone"
v-imask="phoneNumberMask"
#accept="onAccept"
#complete="onComplete"
#keypress="isNumber"
>
<p v-if="$v.phone.$dirty && !$v.phone.required" class="invalid-feedback">Обязательное поле для заполнения</p>
<p v-if="$v.phone.$dirty && !$v.phone.minLength" class="invalid-feedback">Данное поле должно содержать номер телефона</p>
<p v-if="phone_status == 'error'" class="invalid-feedback">Данный номер телефона уже существует</p>
</div>
<div class="authentication-template__enter">
Еще нет аккаунта? <router-link tag="a" :to="url">Войти</router-link>
</div>
<div class="authentication-template__button">
<button class="button" type="submit">
{{buttonText}}
</button>
</div>
</form>
</div>
</div>
</div>
This is my validations:
validations: {
phone: {required, minLength: minLength(16)},
},
This is my function where does this validation work:
submitHandler(){
this.$v.$touch()
if(!this.$v.$error){
axios.post('http://127.0.0.1:8000/api/v1/check-number/',
{
phone_number: this.phone
}
).then((response) => {
this.phone_status = response.data.status
if(this.phone_status == 'success'){
localStorage.setItem('phone', this.phone)
this.$router.push('/register/2')
}
})
}
}
I enter a value in the field that matches the validation, but after if(!this.$v.$error), my axios request doesn't work, I suspect my if condition is wrong, I'm sitting with this problem for a long time, please can anyone help me?
UPD: if i comment this.$v.$touch() my axios request is work, as I understand it, my form still does not pass validation?
Related
i'm trying to add a collection in fireBase fireStore so i used this function .collection.(doc).set ; the collection was not created and the console show error register , and despite that i find the new user in authentification in firebase , i hope that i find the good solution . i'm getting crazy
<div class="uk-position-small uk-position-center uk-overlay uk-overlay-default">
<form #f="ngForm" (ngSubmit)="register(f)">
<div class="uk-margin">
<div class="uk-inline">
<span class="uk-form-icon" uk-icon="icon: happy"></span>
<input class="uk-input" type="text" name="firstName" #firstName="ngModel" ngModel required>
<p class="alert alert-danger" *ngIf="firstName.errors?.required && firstName.touched">this input firstName and lastName are required</p>
</div>
</div>
<div class="uk-margin">
<div class="uk-inline">
<textarea class="uk-input" cols="28" rows="10" placeholder="bio" name="bio" #bio="ngModel" ngModel bio required></textarea>
<p class="alert alert-danger" *ngIf="bio.errors?.required && bio.touched">this bio isrequired</p>
</div>
</div>
<div class="uk-margin">
<div class="uk-inline">
<span class="uk-form-icon" uk-icon="mail"></span>
<input class="uk-input" type="text" name="email" #email="ngModel" ngModel email required>
<p class="alert alert-danger" *ngIf="email.errors?.required && email.touched">this input email is required</p>
</div>
</div>
<div class="uk-margin">
<div class="uk-inline">
<span class="uk-form-icon uk-form-icon-flip" uk-icon="icon: lock"></span>
<input class="uk-input" type="password" name="password" #password="ngModel" ngModel password required minlength="8">
<p class="alert alert-danger" *ngIf="password.errors?.required && password.touched">this input password is required</p>
<p class="alert alert-danger" *ngIf="password.errors?.minlength && password.touched">this input password should +8 caratere</p>
</div>
</div>
<div class="uk-margin">
<div class="uk-inline">
<span class="uk-form-icon uk-form-icon-flip" uk-icon="icon: lock"></span>
<input class="uk-input" type="password" name="confirmPassword" #confirmPassword="ngModel" ngModel required minlength="8">
<p class="alert alert-danger" *ngIf="confirmPassword.errors?.required && password.errors?.minlength && confirmPassword.touched">this input confirmpassword is required</p>
<p class="alert alert-danger" *ngIf="password.value!==confirmPassword.value && password.touched">not equal</p>
</div>
</div>
<button type="submit" class="btn btn-success">Register</button>
</form>
</div>
export class RegisterComponent implements OnInit {
constructor(private as:AuthService , private fs:AngularFirestore , private route:Router) { }
ngOnInit(): void {
}
register(f){
// console.log(f.value)
let data=f.value
this.as.signUp(data.email,data.password ).then((user)=>{
this.fs.collection("users").doc(user.user.uid).set({
firstName:data.firstName,
email:data.email,
bio:data.bio,
uid:data.user.user.uid
})
.then(()=>{
console.log('done')
// this.route.navigateByUrl('/home')
})
})
.catch(()=>{
console.log('error register')
})
}
}
#Injectable({
providedIn: 'root'
})
export class AuthService {
user: Observable<firebase.User>;
constructor(private fa:AngularFireAuth) {
this.user=this.fa.user
}
signUp(email,password){
return this.fa.createUserWithEmailAndPassword(email,password)
}
signIn(email,password){
return this.fa.signInWithEmailAndPassword(email,password)
}
}
You're not returning promises in your chain so your code is blowing right by them. If this doesn't solve your issue, then the problem is in your signUp code and you'd have to post that for more help.
register(f){
let data=f.value
this.as.signUp(data.email, data.password).then((user) => {
// You need to return this promise. Right now, your code
// is blowing right by it and immediately calling the next `then`
return this.fs.collection("users").doc(user.user.uid).set({
firstName: data.firstName,
email: data.email,
bio: data.bio,
uid: data.user.user.uid
})
}).then(() => {
// This code block has now waited for the doc to be set
console.log('done')
// this.route.navigateByUrl('/home')
}).catch((error) => {
console.log('error register')
console.log(error)
})
}
I have defined isError as false in data, however once there is an error from laravel i get the 422 error. I would like to then define isError as true but when i do it i get an error from the console saying that iserror is undefined even though it has been defined. What is the problem?
The error is as per below:
app.js:1925 Uncaught (in promise) ReferenceError: isError is not defined
Thanks
<template>
<div class="contact-section">
<div class="container">
<div class="section-content row">
<div class="contact-text col-lg-6">
<div class="text-box">
<h1 class="subtitle text-white">Contact</h1>
<h2 class="text-white"> Have You Any Project? <br> Please Drop a Message </h2>
<p class="text-white"> Get in touch and let me know how i can help. Fill out the form and i’ll be in touch as soon as possible. </p>
</div>
<ul class="contact-info">
<li>
<img src="assets/images/icons/email.png" alt="Email">
<div>
<strong>Email:</strong>
<ul>
<li>info#nafie.com</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="col-lg-6">
<form class="contact-form form-styled" #submit.prevent="send">
<div class="group">
<label>Name</label>
<div class="control has-prefix-icon">
<input type="text" name="name" placeholder="e.g. John Doe" minlength="3" v-model="form.name">
</div>
</div>
<div class="group">
<label>Email</label>
<div class="control has-prefix-icon">
<input class="ltr-dir" type="email" name="email" placeholder="e.g. john.doe#gmail.com" v-model="form.email">
</div>
</div>
<div class="group">
<label>Message</label>
<div class="control has-prefix-icon">
<textarea name="message" placeholder="Write message..." v-model="form.message"></textarea>
</div>
</div>
<div class="group">
<p v-if="isError" class="error large">All fields are required</p>
<div class="control"><button class="submit-btn btn btn-dark" type="submit">Send</button></div>
</div>
</form>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data: function() {
return {
form: {
email: '',
message: '',
name: ''
},
errors: {},
isError: false
}
},
methods: {
send: function() {
// Reset is error
this.isError = false;
axios.post("/send", this.form)
.then(function (response) {
// Reset form on success
this.form.name = '';
this.form.email = '';
this.form.message = '';
console.log(response);
})
.catch(function (error) {
// Says here undefined?
this.isError = true;
console.log(error);
console.log(error.response.data.errors);
});
}
}
}
</script>
send: function()
{
// Reset is error
this.isError = false;
let self = this;
axios.post("/send", this.form).then(function(response)
{
// Reset form on success
self.form.name = '';
self.form.email = '';
self.form.message = '';
console.log(response);
}).catch(function(error)
{
// Says here undefined?
self.isError = true;
console.log(error);
console.log(error.response.data.errors);
});
}
I would like to show the backend error messages on my Vue component, so for doing that I have created this component:
<template>
<section class="p-0 d-flex align-items-center">
<div class="container-fluid">
<div class="row">
<!-- Right START -->
<div class="col-md-12 col-lg-8 col-xl-9 mx-auto my-5 position-relative">
<!-- Shape Decoration END -->
<div class="row h-100">
<div
class="
col-md-12 col-lg-10 col-xl-5
text-start
mx-auto
d-flex
align-items-center
"
>
<div class="w-100">
<h3>Sign up for your account!</h3>
<p>
Join us today! Create your account easily with less
information.
</p>
<!-- Form START -->
<form class="mt-4" #submit.prevent="submit">
<!-- Email -->
<div class="mb-3">
<label class="form-label" for="email">Email address</label>
<input
v-model="data.name"
v-bind:class="{ 'is-invalid': validate.email }"
required
type="email"
class="form-control"
id="email"
aria-describedby="emailHelp"
placeholder="E-mail"
/>
<div class="invalid-feedback">
{{ validate.email }}
</div>
<small id="emailHelp" class="form-text text-muted"
>We'll never share your email with anyone else.</small
>
</div>
<!-- Username -->
<div class="mb-3">
<label class="form-label" for="email">Username</label>
<input
v-model="data.username"
v-bind:class="{ 'is-invalid': validate.username }"
required
type="text"
class="form-control"
id="username"
placeholder="Username"
/>
<div class="invalid-feedback">
{{ validate.username }}
</div>
</div>
<!-- Password -->
<div class="mb-3">
<label class="form-label" for="password">Password</label>
<input
v-model="data.password"
v-bind:class="{ 'is-invalid': validate.password }"
required
type="password"
class="form-control"
id="password"
placeholder="*********"
/>
<div class="invalid-feedback">
{{ validate.password }}
</div>
</div>
<!-- Password -->
<div class="mb-3">
<label class="form-label" for="password2"
>Confirm Password</label
>
<input
v-model="data.password2"
v-bind:class="{ 'is-invalid': validate.password2 }"
type="password"
class="form-control"
id="password2"
placeholder="*********"
/>
<div class="invalid-feedback">
{{ validate.password2 }}
</div>
</div>
<!-- Checkbox -->
<div class="mb-3 form-check">
<input
type="checkbox"
class="form-check-input"
id="remember"
/>
<label class="form-check-label" for="remember"
>keep me signed in</label
>
</div>
<!-- Button -->
<div class="row align-items-center">
<div class="col-sm-4">
<button type="submit" class="btn btn-dark btn-line">
Sign me up
</button>
</div>
<div class="col-sm-8 text-sm-end">
<span class="text-muted"
>Already have an account?
Signin here</span
>
</div>
</div>
</form>
<!-- Form END -->
<div class="bg-dark-overlay-dotted py-2 my-4"></div>
</div>
</div>
</div>
</div>
<!-- Right END -->
</div>
</div>
</section>
</template>
<script lang="ts">
import { defineComponent, reactive, ref } from "vue";
import { useRouter } from "vue-router";
export default defineComponent({
name: "Register",
setup(props) {
const data = reactive({
username: "",
email: "",
password: "",
password2: "",
});
const validate = reactive({
email: "",
username: "",
password: "",
password2: "",
});
const router = useRouter();
const submit = async () => {
const res = await fetch(`${process.env.VUE_APP_API_URL}/auth/register`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
if (!res.ok) {
const errors = await res.json().then((response) => response.errors);
for (const err of errors) {
const param: string = err.param ?? "";
validate[param] = err.msg;
}
}
};
return {
data,
validate,
submit,
};
},
});
</script>
as you can see I have defined and also exposed the validate property, which contains all the fields of the form.
When the API call is executed on the form submit, I reiceve this response if the backend validation fails:
{
"errors": [
{
"value": "",
"msg": "username must be at least 4 characters long",
"param": "username",
"location": "body"
},
{
"value": "test#",
"msg": "password confirm is different",
"param": "password2",
"location": "body"
}
]
}
I binded the validate property to each input field, so if the value entered in a specific field is incorrect, an error will be appended near the field and also the is-invalid class of Bootstrap is applied.
The errors variable contains the response above, what I'm trying to do is assign to each property of validate (which are the same name of the fields), the error messages, and I did:
const param: string = err.param ?? "";
validate[param] = err.msg;
the problem's that I get:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ email: string; username: string; password: string; password2: string; }'.
No index signature with a parameter of type 'string' was found on type '{ email: string; username: string; password: string; password2: string; }'.
How can I fix this situation? And also, is there a better way to handle such scenario? 'cause I'm new to Vue and most probably I'm overcomplicating the situation here.
Kind regards
If you decided to add TypeScript to your project, it would be a good idea to start using it as intended, so let's firstly make a type for your error object:
type MyTypedError = {
value: string,
msg: string,
// the question mark indicates that the "param" property may not exists
// "typeof" infers the type of the "validate" variable (object in your case)
// "keyof" grabs all the property names from "validate":
param?: keyof typeof validate,
location: string
}
Let's make use of it. Now the TypeScript compiler will know the type of the received data.
if (!res.ok) {
// specify the type of the "errors" variable:
// MyTypedError[] (array of MyTypedError objects)
const errors: MyTypedError[] = await res.json().then((response) => response.errors);
...
}
The problem with your code: you are only guaranteeing that the param variable is type of string, but you don't promise the compiler that param holds any of the property names from validate. But since the compiler knows the type of err, it will even guide you how to make a working loop:
for (const err of errors) {
// We stated that 'param' property might not exist
if (err.param !== undefined) validate[err.param] = err.msg
}
EDIT: The assumption that err.param can also be undefined came from your code: err.param ?? "", though I don't see any reason why would it be.
i have one registration page when user renter some values ,after successfully submission the form need to be clear all the field for that i am using predefined function called reset() inside the script section ,it's not working i am unable to get where did i mistake and one more thing autocomplete="off" is also not working please help me to fix this issue.
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 id="myForm" #submit.prevent="handlesubmit">
<div class="fullname">
<p>FullName</p>
<input type="text" 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" v-model="Password" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$!%*?&])[A-Za-z\d#$!%*?&]{6,}$" required>
<i class="bi bi-eye-slash" id="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" #click="clear();" 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'
},
clear(){
document.getElementById("myForm").reset();
},
handlesubmit() {
let userData = {
FullName: this.FullName,
EmailID: this.EmailID,
Password: this.Password,
Mobile: this.Mobile
}
service.userRegister(userData).then(response => {
// console.log("user Details", response);
alert("user registered successfully");
return response;
}).catch(error => {
alert("Invalid Email/Mobile number");
return error;
})
}
}
}
</script>
<style lang="scss" scoped>
#import "#/styles/Register.scss";
</style>
try this:
in your HTML
<form ref="myForm" #submit.prevent="handlesubmit">
in your handlesubmit, after it finishes
this.$refs.myForm.reset();
about autocomplete, found this:
In order to provide autocompletion, user-agents might require elements to:
Have a name and/or id attribute
Be descendants of a element
The form to have a submit button
try adding a name or id to the input.
In an example of a Vue wizard form I tried to add form validation with Joi. How do I set this up logically? The goal is to controll the fields before moving to the second and last page with the next() method. Because of the simplicity of this wizard form, I don't want to change to VueFormWizard. To increase the code I erased a lot of fields etc..
<template>
<div>
<div v-if="errorMessage" class="alert alert-danger" role="alert">
{{errorMessage}}
</div>
<form>
<div v-if="step ===1 ">
<div class="form-group">
<label for="title">Title</label>
<input v-model="example.title"
type="text"
class="form-control"
id="title" />
</div>
<button #click.prevent="next()">Next step</button>
</div>
<div v-if="step === 2">
<div class="form-group">
<label for="userName">Email.</label>
<input v-model="example.userName"
type="email"
class="form-control"
id="userName" />
</div>
<button #click.prevent="prev()">Go back</button>
<button #click.prevent="createExample" type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</template>
<script>
import Joi from 'joi'
const schema = Joi.object().keys({
title: Joi.string().alphanum().min(2).max(40).required(),
userName: Joi.string().email(),
})
export default {
data: () => ({
step: 1,
errorMessage: false,
example: {
title: '',
userName: ''
}
}),
watch: {
example: {
handler () {
this.errorMessage = ''
},
deep: true
}
},
methods: {
prev () {
this.step--
},
next () {
this.step++
if (this.validUser()) {
return false
}
},
createExample () {
// Post request
},
validUser () {
const result = Joi.validate(this.huismap, schema)
return true
if (result.error.message.includes('title')) {
this.errorMessage = 'Vul een titel in van min 2 karakters'
return false
}
}
}
</script>
You can make use of browser validation if you set it up like this:
<form #submit.prevent="submitMyForm">
<input v-model="form.title" required minlength="4" maxlength="20" />
<button type="submit">Submit</button>
</form>
Now your browser will prevent you from submitting the form if title is empty, if the length is less than 4 or greater than 20.
This solution can do a lot of stuff, even regex checking:
https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation#Validating_against_a_regular_expression
However this is limited to a small set of checks and is not supported by older browsers. If you need very specific validation you'd have to use a custom solution, which is described here https://v2.vuejs.org/v2/cookbook/form-validation.html.