Vuetify validate textfield on input - javascript

<v-text-field v-model='postal_code'
validate-on-blur
name="postal_code"
:maxlength="postalCodeLength(postal_code)"
ref="postalCode"
#input="handle(postal_code, 'postalCode')"
:rules="postalCodeRules"
required
:disabled="disabledPostalCode">
</v-text-field>
I want the validation message to appear as soon as the user starts typing on the text field. But the validation message appears when the user leaves the textfield and starts entering data on another textfield. I think this is because of validate-on-blur but if remove validate-on-blur then the validation message appears all the time even if the user is not entering data on this field. Help me resolve this issue.

Take a look at following snippet (you can make condition, in your rule, that postal_code is not empty, and remove validate-on-blur)
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
postal_code: '',
postalCodeRules: [
value => {
const patern = /^[A-z]\d[A-z] \d[A-z]\d$|^\d\d\d\d\d$/
if(this.postal_code) return patern.test(value) || 'Please use the format A0A 0A0 or 12345'
else return true
}],
disabledPostalCode: false
}
},
methods: {
handle() {},
postalCodeLength() {}
}
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app>
<v-main>
<v-container>
<v-text-field v-model='postal_code'
name="postal_code"
:maxlength="postalCodeLength(postal_code)"
ref="postalCode"
#input="handle(postal_code, 'postalCode')"
:rules="postalCodeRules"
required
:disabled="disabledPostalCode">
</v-text-field>
</v-container>
</v-main>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>

Instead of adding multiple attributes for a validation (maxlength, required, etc..), You can simply add these validations in your :rules object, Rest will take care by the Vuetify and Vue.
If you want to handle any logics on input change, Then you can achieve that by using #input event and based on the validation rule passed, You can put that logic accordingly.
Here is the live demo (Just for a demo purpose I added only required field validation) :
new Vue({
vuetify: new Vuetify(),
data: {
name: ''
},
methods: {
validateField() {
this.$nextTick(() => {
if (this.$refs.nameInput.validate()) {
console.log('name field validation passed')
} else {
console.log('name field validation failed')
}
})
}
}
}).$mount('#app');
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css"/>
<div id="app">
<v-text-field
outline
v-model="name"
label="Enter Your Name"
:rules="[(v) => !!v || 'Name is required']"
#input="validateField"
ref="nameInput"
/>
</div>

Related

bind dynamic expression in a variable

I'm creating a Vue application in which an expression will come from config as a variable. I need to run the expression (something like eval in javascript) and apply result to attribute
eg:
<v-text-field placeholder="{{expression}}"></v-text-field>
But this is showing the expression , not evaluating. Any way to achieve this?
Edit
Here expression can be something like
data.option=1?"ABC":"BCD"
You can try with eval but be aware::
const out = 'data.option === 1 ? "ABC" : "BCD"'
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
data: {option: 1}
}
},
computed: {
expression() {
return eval(JSON.parse(JSON.stringify('this.' + out)))
}
}
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app>
<v-main>
<v-container>
<v-text-field :placeholder="expression"></v-text-field>
</v-container>
</v-main>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
You can try to add colon before the property like following. To indicate that there is an expression in the middle of the quotation mark
<v-text-field :placeholder="expression"></v-text-field>

Get an element by its ref in vue and give it focus

I'd like to give focus to a vue input when a button is pressed. My understanding is that I need the html element, which I get by setting a ref value, then saying:
this.$refs.theRefName.$el.focus();
But I'm getting tripped up on the refs part of that expression. See the MRE below where refs contains the correct keys, but the values are empty. As a result .$el is undefined and the expression errs.
I've seen SO articles that deal with this being undefined (not a problem for me) or $refs being empty because the element was conditionally rendered (also, not a problem for me). I've got $refs, but why does it contain empty objects?
Vue.config.productionTip = false;
Vue.config.devtools = false;
var app = new Vue({
el: '#app',
data: {
message: 'World'
},
methods: {
click() {
alert(JSON.stringify(this.$refs))
// here's what I want to do, but I can't because inp2 is empty
// this.$refs.inp2.$el.focus();
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h1>Why are refs empty objects?</h1>
<input ref="inp1"></input><br/><br/>
<input ref="inp2" placeholder="i want focus on click"></input><br/><br/>
<button #click="click">Click me</button>
</div>
If you can help me get to the html element and give it focus, I'd be much obliged.
Try without $el :
Vue.config.productionTip = false;
Vue.config.devtools = false;
var app = new Vue({
el: '#app',
data: {
message: 'World'
},
methods: {
click() {
this.$refs.inp2.focus();
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.css" />
<script src="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue-icons.min.js"></script>
<div id="app">
<h1>Why are refs empty objects?</h1>
<input ref="inp1" /><br/><br/>
<b-form-input ref="inp2" placeholder="i want focus on click"></b-form-input>
<button #click="click">Click me</button>
</div>

Check if string is in an array of objects VueJS?

I have a text field where a user can input the value and then on click of a button push the value inside an array. The value i want to test for is the uniqueID. So let's say if the user inputs multiple values including comma or white spaces and one of them matches the uniqueId in the existing array. Then i get an alert.
I tried using some but that didn't quite work. Not sure what i am doing wrong.
Here is a sample pen
new Vue({
el: "#app",
data() {
return {
myArray: [{
title: "Sam",
age: 36,
uniqueId: "GHTR435"
},
{
title: "Max",
age: 44,
uniqueId: "MLKT432"
}
],
inputField: "",
inputArray: []
};
},
methods: {
createArray() {
if (this.myArray.some((el) => el.uniqueID === this.inputField)) {
alert("Heyy!!!!");
} else {
this.inputArray.push(this.inputField.trim().replace(/, +/g, ","));
console.log(this.inputArray);
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.css" rel="stylesheet" />
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout justify-center>
<v-flex xs6>
<v-text-field solo v-model="inputField"></v-text-field>
<v-btn #click="createArray">Click Me</v-btn>
</v-flex>
</v-layout>
</v-container>
</v-app>
</div>
Any help will be appreciated. Thank you.
if (this.myArray.some((el) => this.inputField.split(/[, ]/g).includes(el.uniqueID))
You have an error in your condition. It should be
this.myArray.some((el) => el.uniqueId /* <-- "d" instead of "D" */ === this.inputField)

Bind a vue input that doesn't exist yet to a data property

We are using Vex in our application for all the dialog messages. I have an input in one of the dialogs that is used to filter a list of items.
In my Vue instance, I want to listen for the changes on a data property.
The problem is that Vue doesn't get the changes as I type them in the input box. I am thinking this is due to the fact that the input is added to the DOM after the Vue initialization.
How would I approach this so my Vue instance can listen to the input changes? I've done my best to recreate the scenario in it's most simple form in the snippet below.
new Vue({
el: '#app',
data: {
filter: ''
},
methods: {
openModal: function() {
vex.dialog.open({
input: [
'<h2>Filter</h2>',
'<input v-model="filter" />',
'<p>{{filter}}</p>'
].join('')
})
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vex-js/4.0.0/js/vex.combined.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/vex-js/4.0.0/css/vex.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button v-on:click="openModal">Open Modal</button>
</div>
The issue is that you are providing plain html in strings to the vex.dialog.open method. Vue won't have any idea that you have done this and so none of the Vue syntax that you've included in those strings will be interpreted as it would in a Vue component definition.
What you should do is make a Vue component for that input, and then pass that input's element via a ref to the vex.dialog.open method. That way, Vue will have compiled the template before it's used in the dialog.
Here's a simple example:
Vue.component('my-input', {
template: `
<div>
<h2>Filter</h2>
<input v-model="filter"/>
<p>{{filter}}</p>
</div>
`,
data() {
return {
filter: ''
}
}
});
new Vue({
el: '#app',
data() {
return {
modalOpened: false
}
},
methods: {
openModal() {
vex.dialog.open({
input: this.$refs.input.$el
});
this.modalOpened = true;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vex-js/4.0.0/js/vex.combined.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/vex-js/4.0.0/css/vex.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="openModal">Open Modal</button>
<my-input v-show="modalOpened" ref="input"/>
</div>

How to bind input value to the return output of a method in Vue.js?

I am using a Vuetify checkbox component and I am trying to bind it's value to the output of my method but it is not working at all. I have tried it with a computed property but I could not pass and argument to it. And it is also not working if I use a method. Is there a way to dynamically assign a value to an input like this?
<div v-for="row in rows">
<v-checkbox :value="isSelected(row.id)"></v-checkbox>
</div>
data()
{
return {
rows: [{id: 22546}, {id: 3521}, {id: 15698}],
selected: [1259, 1898, 3521]
}
},
methods:
{
isSelected(id)
{
if (this.selected.indexOf(id) > -1) {
return true
} else {
return false
}
}
}
When I tried with v-model instead if :value it gave me this error:
<v-checkbox v-model="isSelected(row.id)"></v-checkbox>
isSelected(id)
{
return true
},
error
[Vue warn]: Failed to generate render function:
SyntaxError: missing ) after argument list in
Try with:
<v-checkbox :input-value="isSelected(row.id)"></v-checkbox>
You can use v-model with getter that encapsulates the logic that decides if checkbox needs to be checked:
let id = 1898;
new Vue({
el: '#app',
data() {
return {
rows: [{id: 22546}, {id: 3521}, {id: 15698}],
selected: [1259, 1898, 3521]
}
},
computed: {
val: {
get: function() {
return this.selected.indexOf(id) > -1;
},
set: function(newValue) {
console.log(newValue);
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
<div id='app'>
<div v-for="row in rows">
<v-checkbox v-model="val"></v-checkbox>
</div>
</div>
It works fine with v-model make sure your app is nested inside v-app tag :
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({ el: '#app',
data()
{
return {
rows: [{id: 22546}, {id: 3521}, {id: 15698}],
selected: [1259, 1898, 3521]
}
},
})
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
<div id="app">
<v-app>
<div v-for="(row,i) in rows">
<v-checkbox
v-model="selected[i]"
:label="`${selected[i] > -1 ? true : false} `"
></v-checkbox>
</div>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
</body>
</html>
Ok, I figure it out,
v-model is 2-way binding, you can only bind it to variable or computed property with getter and setter.
value provided by vue-checkbox component is not the value of checkbox checked/unchecked state. You can set initial state with :input-value.

Categories

Resources