Trying to set up a basic "Are you sure you want to leave this page" type prompt on a page containing a simple html form.
Form:
<!DOCTYPE html>
<html>
<head></head>
<body>
<div id="app">
<form id="webform" action='#' method='POST' #submit.prevent="doSubmit()">
<input v-validate="'required'" :class="{'input': true, 'is-danger': errors.has('cust_name_first') }" name="cust_name_first" type="text">
<span v-show="errors.has('cust_name_first')" class="help is-danger">{{ errors.first('cust_name_first') }}</span>
</form>
</div>
<!-- div id app -->
</body>
</html>
And the javascript:
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vee-validate/2.0.9/vee-validate.min.js"></script>
<script>
formsubmitval = 1;
Vue.use(VeeValidate);
new Vue({
el: "#app",
template: '#app',
data() {
return {
cust_name_first: null,
cust_id: null,
sales_name_first: null,
};
},
methods: {
doSubmit() {
this.$validator.validateAll().then(function(result){
if (!result){
//this means a validation failed, so exit without doing anything
return;
}
//here you would put your form submit stuff
formsubmitval=0;
document.getElementById('webform').submit();
});
}
}
});
if (formsubmitval==1)
{
window.onbeforeunload = function(e) {
e = e || window.event;
e.preventDefault = true;
e.cancelBubble = true;
e.returnValue = 'test';
}
}
</script>
The problem is that I'm not being prompted to leave the page, and any user entered data is lost. What am I doing wrong with the script above?
I was making this more difficult than it needed to be. Just needed to add onbeforeunload event, and then set it to null when sumbmitting. Works a treat.
Updated javascript:
<script>
window.onbeforeunload = function() {
return true;
};
Vue.use(VeeValidate);
new Vue({
el: "#app",
template: '#app',
data() {
return {
cust_name_first: null,
cust_id: null,
sales_name_first: null,
};
},
methods: {
doSubmit() {
this.$validator.validateAll().then(function(result){
if (!result){
//this means a validation failed, so exit without doing anything
return;
}
//here you would put your form submit stuff
window.onbeforeunload = null;
document.getElementById('webform').submit();
});
}
}
});
</script>
Related
I am really new to Vue and for this project I am using email validation followed by reg on VUE Script Data. When I print out the console.log(this.reg.test(this.email)) , while the user is filling the email input field, it validates correctly as true or false. NEXT button stays disable for both true and false case. Can we make the button enable, once the console.log(this.reg.test(this.email)) is true.
View
<div id="app">
<h2>Todos:</h2>
<input type="email" v-model="email" placeholder="enter email email address"/>
<button v-bind:disabled="isDisableComputed">NEXT</button>
</div>
Script
new Vue({
el: "#app",
data: {
email: '',
reg: /^(([^<>()\[\]\\.,;:\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,24}))$/
},
methods: {
toggle: function(todo){
todo.done = !todo.done
}
},
computed: {
isDisableComputed() {
if(this.reg.test(this.email) == 'true'){
console.log(this.reg.test(this.email));
return false;
}
else{
console.log(this.reg.test(this.email));
return true;
}
},
}
})
Below is my code uploaded on JSFIDDLE
https://jsfiddle.net/ujjumaki/9es2dLfz/6/
Look into MDN: RegExp, RegExp.test return boolean, not one string. So this.reg.test(this.email) == 'true' will be always false.
let regex = /^(([^<>()\[\]\\.,;:\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,24}))$/
console.log("regex.test('test#test.com') ==> ", regex.test('test#test.com'))
console.log("regex.test('test#test.com')=='true' ==> ", regex.test('test#test.com') == 'true')
console.log("regex.test('test#test.com') ==> ", regex.test('test#test#.com'))
console.log("regex.test('test#test#.com')=='true' ==> ", regex.test('test#test#.com') == 'true')
So uses return !this.reg.test(this.email) instead like the computed property=isDisableComputed in below snippet.
new Vue({
el: "#app",
data () {
return {
email: '',
reg: /^(([^<>()\[\]\\.,;:\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,24}))$/
}
},
methods: {
toggle: function(todo){
todo.done = !todo.done
}
},
computed: {
isDisableComputed() {
return !this.reg.test(this.email)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Todos:</h2>
<input type="email" v-model="email" placeholder="enter email email address"/>
<button :disabled="isDisableComputed">NEXT ({{isDisableComputed}})</button>
</div>
The changes are not reflected in DOM, even when the data is changing properly. Here is a very basic example to demonstrate the issue -
<template>
<input type="text" v-model="username" />
<p>{{error}}</p>
<button #click="saveData">Save</button>
</template>
<script>
export default {
data () {
model.error = ''; // adding a new property
return model; // 'model' is a global variable
}
methods: {
saveData() {
if (!this.username) {
this.error = 'Please enter the username!';
return;
}
// ... other code
}
}
};
</script>
After calling saveData() the error variable contains the message if username is not filled. But it's not showing up in the paragraph.
There is a trick. If I also change the username property when the error variable is changed, the changes are reflected.
You need to return error or Vue doesn't have access to it.
data () {
return {
error: '',
model: model,
};
}
You should be able to achieve what you're trying to do, as long as error and username properties are defined on model for data. I've included a simple snippet below, showing it working. Take a look at Declaring Reactive Properties in the documentation.
var model = {
username: "Default"
};
new Vue({
el: "#app",
data: () => {
model.error = model.error || "";
return model;
},
methods: {
updateError() {
this.error = "Test";
},
updateUsername() {
this.username = "Hello, World!";
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button type="button" #click="updateError">Update Error</button>
<button type="button" #click="updateUsername">Update Username</button>
<div>Error: {{error}}</div>
<div>UserName: {{username}}</div>
</div>
I need a mask for input that needs to have the format of dddd-ddd (Portuguse zip code), I don't feel like importing a library just for this input.
This is what I have right now:
new Vue({
el: '#app',
data: {
zip_code: '2770-315'
},
computed: {
mask_zip_code: {
get: function() {
return this.zip_code;
},
set: function(input) {
input = input.replace(/[^0-9-]/g, "");
if(input.length >= 4) {
input = input.substr(0, 4)+'-'+input.substr(5); // in case people type "-"
}
this.zip_code = input;
}
}
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<input v-model="mask_zip_code" maxlength="8">
</div>
Has you can see the behavior is a little wierd and it allows to type letters as well.
I've updated your snippet to work as you intended it. The computed value works but it will not be reflected in the input, instead a method is more appropriate here
new Vue({
el: '#app',
data: {
zip_code: '2770-315'
},
methods: {
mask_zip: function(event) {
if (event.key && event.key.match(/[a-zA-Z]/)) {
event.preventDefault()
} else {
if(this.zip_code.length >= 4) {
this.zip_code = this.zip_code.substr(0, 4)+'-'+this.zip_code.substr(5); // in case people type "-"
}
}
return this.zip_code;
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<input v-model="mask_zip_code" maxlength="8" #keypress="inputValidation">
{{mask_zip_code}}
</div>
Try using the pattern attribute with a regex:
<script src="https://unpkg.com/vue"></script>
<form>
<input v-model="mask_zip_code" pattern="[0-9]{4}-[0-9]{3}">
<button>Submit</button>
</form>
This should prevent users from submitting the form with anything other than a valid Portuguese zip code.
new Vue({
el: "#app",
data: {
msg: "hello world"
},
methods: {
trigger: function() {
var fileLoader = document.getElementById('fileLoader');
//clear file value
if(fileLoader.files.length > 0) {
fileLoader.value == null;
alert(fileLoader.files[0].name);
}
fileLoader.click();
},
fetchData: function() {
console.log('hello');
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<button #click="trigger">upload image</button>
<input type="file" id="fileLoader" v-show="false" #change="fetchData">
</div>
as you know in chrome, when you first time choose a file, input will trigger onchange event, but second time you choose the same file , input won't trigger onchange event,so i want to set input's value to null,before choose the same file, which works using jquery or plain javascript. but in vuejs, it dosen't work. what's the problem?
You are doing a comparison instead of an assignment:
fileLoader.value == null;
This should be:
fileLoader.value = null;
Also this means you won't be able to alert the filename after you have done this, because the value has already been cleared by then. So this line should come before you clear it:
alert(fileLoader.files[0].name);
new Vue({
el: "#app",
data: {
msg: "hello world"
},
methods: {
trigger: function() {
var fileLoader = document.getElementById('fileLoader');
//clear file value
if(fileLoader.files.length > 0) {
alert(fileLoader.files[0].name);
fileLoader.value = null;
}
fileLoader.click();
},
fetchData: function() {
console.log('hello');
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<button #click="trigger">upload image</button>
<input type="file" id="fileLoader" v-show="false" #change="fetchData">
</div>
I'm having my practice in VueJS 1.0 and I am learning about Components.
in this example, there is an input element and has to supply coupon or some kind of a code from an API. and I have to validate. I have my <coupon > component and has props of when-applied. The when-applied must call the parent function setCoupon but it won't.
I only got this error this.whenApplied is not a function.
<div id="demo" class="list-group">
<script id="coupon-template" type="x-template">
<input type="text" v-model="coupon" v-on:blur="whenCouponHasBeenEntered">
<div v-text="text"></div>
</script>
<coupon when-applied="setCoupon"></coupon>
</div>
Here is my app.js file
Vue.component('coupon', {
template: '#coupon-template',
props: ['whenApplied'],
data: function() {
return {
coupon: '',
invalid: false,
text: ''
}
},
methods: {
whenCouponHasBeenEntered: function() {
this.validate();
},
validate: function() {
if( this.coupon == 'FOOBAR') {
this.whenApplied(this.coupon);
return this.text = '20% OFF!!';
}
return this.text = 'that coupon doesn`t exists';
}
}
});
new Vue({
el: '#demo',
methods: {
setCoupon: function(coupon) {
alert('set coupon'+ coupon);
}
}
});
Someone pls help. Suggestions pretty much appreciated.
You should bind the property:
<coupon v-bind:when-applied="setCoupon"></coupon>
or you could use the shorthand syntax for v-bind:
<coupon :when-applied="setCoupon"></coupon>
Read more about the props here.