Checkbox validation and rerouting in VUE.js - javascript

I am trying to validate the check box and navigate to next link for ex google.com. I found the solution for checkbox validation from the below link
Vue JS - Checkbox validation error on submit from #wolfrevo
new Vue({
el: "#app",
data: {
termsState: false,
validated: false,
nextPageUrl:'www.google.com'
},
computed: {
termsError() {
return this.validated && !this.termsState
}
},
methods: {
handleTermsState() {
this.validated = false
},
handleSubmit() {
this.validated = true
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id='app'>
<label for="terms">
Terms and Privacy Policy
<input type="checkbox" id="terms" name="terms" v-model="termsState" #change="handleTermsState">
{{ termsState }}
</label>
<p style="color: red" class="for-error terms-error" v-if="termsError">You have to agree the terms and privacy condition.</p>
<router-link :to="nextPageUrl">
<div><button type="submit" #click="handleSubmit">Submit</button></div>
</router-link>
</div>
I tried adding router-link, it is redirecting even without validating the checkbox. what is that I am missing?

Related

Vue can't check the recently unchecked, checkbox even its binding

I have a list of checkboxes, I want when I click on input 4th all previous boxes being checked and the rest unchecked.
I almost did it, but there is an issue that when I back to the those checked boxes and uncheck one of them, its still okay and the next being unchecked, but when again going forward and check another one from those unchecked the recently unchecked item being still unchecked and not changed.
here is the demo, and I think the GIF will describe my issue better.
Demo https://jsfiddle.net/j5dpkut8/1/
<script src="https://unpkg.com/vue"></script>
<div id="app">
<input type="checkbox" v-model="checked[0]" value="0" #change="printState(0)"> checked 0 <br>
<input type="checkbox" v-model="checked[1]" value="1" #change="printState(1)"> checked 1 <br>
<input type="checkbox" v-model="checked[2]" value="2" #change="printState(2)"> checked 2 <br>
<input type="checkbox" v-model="checked[3]" value="3" #change="printState(3)"> checked 3 <br>
<input type="checkbox" v-model="checked[4]" value="4" #change="printState(4)"> checked 4 <br>
<input type="checkbox" v-model="checked[5]" value="5" #change="printState(5)"> checked 5 <br>
<input type="checkbox" v-model="checked[6]" value="6" #change="printState(6)"> checked 6 <br>
<input type="checkbox" v-model="checked[7]" value="7" #change="printState(7)"> checked 7 <br>
</div>
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!',
checked: [
false,false,false,false,false,false,false,false,
],
},
methods: {
printState(x) {
this.checked = [
false,
false,
false,
false,
false,
false,
false,
false,
],
for (let i = 1; i < this.checked.length; i++) {
if (i <= x) {
this.checked[i] = true;
}
}
console.log(this.checked);
},
}
})
In your code change change handler into click handler and all will be okey.
Or.
new Vue({
el: '#app',
data: {
checked: [
{ state: false },
{ state: false },
{ state: false },
{ state: false },
{ state: false },
{ state: false },
{ state: false },
{ state: false },
],
},
methods: {
printState(x) {
for (let i = 0; i < this.checked.length; i++) {
this.checked[i].state = i <= x ? true : false;
}
},
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<div v-for="(n, index) in checked" :key="index">
<input
type="checkbox"
v-model="n.state"
#click="printState(index)"
>
<span>checked {{ index }} {{ n.state }}</span>
</div>
</div>
As #TigranAbrahamyan mentioned, #click will fix it. But here is a solution in very few lines that also uses v-model and value as intended and lets you easily adjust the number of boxes.
new Vue({
el: "#app",
data: () => ({ num: 10, values: [] }),
methods: {
mark(index) {
this.values = [...Array(index).keys()];
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="index in num" :key="index-1">
<input type="checkbox" v-model="values" :value="index-1" #click="mark(index-1)" />
</div>
</div>

Email validation in Vue.js

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>

Form validation in vue

I am trying to understand and work around to validate a simple form but the problem I am facing is, when the page loads, it shows the "Error" or "Success" message, which should display only either on keypress or mouseout event.
Moreover, I cannot figure out how to validate the dropdown and finally when a user click submit, it can check all fields are filled and correct to submit the form. Following is my code and my link to JSFiddle
HTML
<div id="app">
<div>
<label for="name">Name</label>
<input type="text" #keypress="checkField" v-model="name">
<span v-if="checkName">Checks out </span>
<span v-if="!checkName">Pleas enter valid name</span>
</div>
<div>
<label for="Age">Age</label>
<input type="number" #keypress="checkField2" v-model="age">
<span v-if="checkAge">Enter Valid Age </span>
<span v-if="!checkAge">Not a valid age</span>
</div>
<div>
<select name="" id="">
<option disabled selected>Please Choose</option>
<option v-for="gender in genders" :value="gender">
{{gender}}
</option>
</select>
<span v-if="genderField">Please select a gender</span>
<span v-if="!genderField">Green means go</span>
</div>
<div>
<button #click="checkSubmit(e)">Submit</button>
</div>
</div>
JS
data: {
name: "",
checkName: "",
age: "",
checkAge: "",
genders : ["Male",'Female',"Other"],
genderField: ""
},
methods: {
checkField() {
if (!this.amount) {
this.checkName = true
}
},
checkGender() {
if(!this.genders){
this.genderField = true
}
},
checkSubmit(e){
//check if all fields are filled before submitting
alert("it is working")
e.preventDefault()
}
}
})
There is a lot of ways to validate forms. I have a few tips for this kind of case.
Use a form element with #submit.prevent="..." event handler. It will ensure a better user experience;
Do not use #key* event handlers to validate or format a value, instead, use #input. It will prevent you from a lot of headache;
Vue provide a API to watch all the attribute changes, not only when the user changes it.
For solve your problem, you can create a validation attribute and set its content acording the other attributes change.
See the example below:
BTW: I recommend that you take a look on vuelidate
const app = new Vue({
data() {
return {
name: null,
age: null,
gender: null,
genders: ['Male', 'Female', "Other"],
validations: {}
}
},
methods: {
submit(e) {
const keys = Object.keys(this.validations);
// required fields
const required = ['name', 'age', 'gender'];
for (const key in required) {
if (!keys.includes(required[key])) {
alert('Please, insert a ' + required[key]);
return;
}
}
for (const key in this.validations) {
if (!this.validations[key]) {
alert('Please, insert valid ' + key);
return;
}
}
alert("ok");
}
},
watch: {
name(newValue) {
this.validations.name = newValue > '';
},
age(newValue) {
this.validations.age = newValue > 0;
},
gender(newValue) {
this.validations.gender = this.genders.includes(newValue);
}
}
});
app.$mount("#app");
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<form #submit.prevent="submit">
<div>
<label for="name">Name</label>
<input type="text" v-model="name">
<span v-if="'name' in validations && validations.name">Checks out </span>
<span v-if="'name' in validations && !validations.name">Pleas enter valid name</span>
</div>
<div>
<label for="age">Age</label>
<input type="number" v-model="age">
<span v-if="'age' in validations && !validations.age">Enter Valid Age</span>
</div>
<div>
<label for="gender">Gender</label>
<select name="gender" v-model="gender">
<option disabled selected>Please Choose</option>
<option v-for="gender in genders" :value="gender">
{{gender}}
</option>
</select>
<span v-if="'gender' in validations && validations.gender">Green means go</span>
<span v-if="'gender' in validations && !validations.gender">Please select a gender</span>
</div>
<input type="submit" value="Submit">
</form>
</div>
In Angular, we have a built-in option to validate forms. But Vue offers very limited functionality when it comes to create and validate forms. To add more functionality, we have to install a separate package called Vuelidate to validate our Vue application forms.
What is Vuelidate?
According to the Vuelidate website:
“Vuelidate 2 is a simple, but powerful, lightweight model-based validation for Vue.js 3 and Vue 2.x.”
Install
npm install #vuelidate/core #vuelidate/validators
Reference:
https://aaqibqs.medium.com/learn-form-validation-in-vue-3-in-10-minutes-with-vuelidate-8929c5059e66

Checkbox click invalid data inside v-for loop

I would like to validate at least one need to check the checkbox.
I'm trying to validate when I clicked on checkbox through the loop.
When I checked one, the output is invalid return false in the first click. When I unchecked return true. But when I checked my sizes array data with vue-dev tools data is valid. I'm trying to find that bugs but I didn't find.
I don't know why.I would like to know that's why? Am I wrong?
new Vue({
el: '#app',
data: {
sizes:[
{id:1,name:'small',ischeck:false,price:0},
{id:2,name:'medium',ischeck:false,price:0},
{id:3,name:'large',ischeck:false,price:0}
],
newval:[]
},
methods: {
checkchanged(){
for(var i=0;i<this.sizes.length;i++){
console.log(this.sizes[i].ischeck);
}
}
}
})
<script src="https://unpkg.com/vue#2.5.17/dist/vue.js"></script>
<div id="app">
<span v-for="size in sizes">
<input type="checkbox" v-model="size.ischeck" :value="size.ischeck"
#click="checkchanged">
<label>{{size.name}}</label>
<input type="text" :disabled="!size.ischeck" v-model="size.price">
</span>
</div>
You could do that using computed property which you call error and hide/show the error message according to that property value:
new Vue({
el: '#app',
data: {
sizes:[
{id:1,name:'small',ischeck:false,price:0},
{id:2,name:'medium',ischeck:false,price:0},
{id:3,name:'large',ischeck:false,price:0}
],
newval:[],
},
methods: {
checkchanged(){
for(var i=0;i<this.sizes.length;i++){
console.log(this.sizes[i].ischeck);
}
}
},
computed:{
error(){
for(var i=0;i<this.sizes.length;i++){
if(this.sizes[i].ischeck) return false;
}
return true;
}
}
})
<script src="https://unpkg.com/vue#2.5.17/dist/vue.js"></script>
<div id="app" style="display :flex;flex-direction: column;">
<div v-for="size in sizes">
<input type="checkbox" v-model="size.ischeck" :value="size.ischeck"
#change="checkchanged">
<label>{{size.name}}</label>
<input type="text" :disabled="!size.ischeck" v-model="size.price">
</div>
<div v-if="error" style="color:red">
there's an error !
</div>
</div>
Finally you don't need to that event #click="checkchanged" you can use #change="checkchanged" instead

How can I display required html 5 in vue component?

My vue component like this :
<template>
<div>
...
<form class="form-horizontal" id="form-profile">
...
<input type="number" class="form-control" required>
...
<button type="submit" class="btn btn-primary" #click="submit">Submit</button>
...
</form>
...
</div>
</template>
<script>
export default {
...
methods: {
submit(e) {
e.preventDefault()
if (this.checkForm()) {
// do ajax here
}
},
checkForm() {
let field = true
$('#form-profile :required').each(function(i) {
if(this.checkValidity() == false)
field = false
})
return field
},
}
}
</script>
I using required html5 to validation
I using e.preventDefault() to prevent page redirects. Because I want to using ajax
My problem here is the required validation html5 not show if not filled. Maybe it because I using e.preventDefault()
How can I display the required html5?
In order to work as expected you have to set the v-on:submit method on the form tag, and have a button/input type "submit".
Also, notice the event modifier prevent on the #submit, it's a shorcut to not have to write e.preventDefault() on the method
new Vue({
el: '#app',
data() {
return {
myText: ''
}
},
methods: {
submitForm() {
alert('submited: ' + this.myText)
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.15/vue.js"></script>
<div id="app">
<form #submit.prevent="submitForm">
<input type="text" v-model="myText" required />
<button type="submit">Submit</button>
</form>
</div>

Categories