v-select on close event or remove validation error timer? - vue.js

Final Edit/Solution: https://jsfiddle.net/up9xkhsm/1/
Is there such an event for v-select that I can key on when it is closed? Or some sort of a 'timer' I can set to remove validation errors after they occur?
This is the v-select I am using:
https://vuetifyjs.com/en/components/selects
Edit: this outlines the issue:
https://jsfiddle.net/96vnLm7g/
I want to know when a user clicked on the v-select but did not select anything. It has to be possible, obviously, since the validation can pick up on this..

Use an onChange prop to add your callback function, so you can check for the v-model assigned to v-select if has changed, to clear the validation errors. Or watch the v-model assigned to v-select for changes.
Using onChange:
<v-select :options="options" :on-change="cleanUpValidation" v-model="selectModel" name="some-select"></v-select>
And in VueJS
methods: {
cleanUpValidation(){
//do the cleanup
}
}
By default, onChange emits input event with value of selected option:
default: function (val) {
this.$emit('input', val)
}
So you can use it also to catch the input event:
<v-select :options="options" #input="cleanUpValidation" v-model="selectModel" name="some-select"></v-select>
In VueJS
methods: {
cleanUpValidation(val){
//do something with selected option value or cleanup error
}
}
Or you can watch the model assigned to v-select:
watch: {
'selectModel' : function(){
//do the cleanup or something with this.selectModel
}
}
For onChange and other props see:
https://sagalbot.github.io/vue-select/docs/Api/Props.html
Same thing would apply for VuetifyJS's v-select.
Edit:
Main goal was to clear validation errors when v-select is actually clicked.
v-select uses focus event within its onClick() method, to tell the VueJS that component is clicked, so that can be used to catch the click event:
<v-select
#input="inputChanged"
v-on:change="changeChanged"
label="Select Item"
:items="myItems"
required
:rules="rules.requiredField"
#focus="focusChanged"
>
</v-select>
And in js:
methods:{
focusChanged(){
console.log('focusChanged ');
},
}
For last example: https://jsfiddle.net/c5moqweu/
And see https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/components/VSelect/VSelect.js
onClick
Method

Related

How to make preventDefault for change on Element UI radio group

I'm using Element UI radio button group and I want to use preventDefault() when trigering change event:
<el-radio-group #change="changeHandler" v-model="radio1">
<el-radio-button label="New York"></el-radio-button>
<el-radio-button label="Washington"></el-radio-button>
<el-radio-button label="Los Angeles"></el-radio-button>
<el-radio-button label="Chicago"></el-radio-button>
</el-radio-group>
Script:
methods: {
changeHandler(value, e) {
// e is undefined
// here should be preventDefault
}
}
I tried set second parameter to change function, but it is undefined.
Element UI works a bit differently. #change just returns the value chosen, nothing else. We need to use native to access the Event object. But #change.native won't work, as the change has already happened (if you want to actually prevent the change). As a side note, I would use disabled attribute instead (like presented in documentation). In my opinion for the UX it's weird that a user cannot choose a radio button, but putting that aside.... Use #click.native instead if you want to prevent a choice:
#click.native="changeHandler"
Then you have access to the Event object:
changeHandler(e) {
console.log(e.target.value)
if(e.target.value == "Washington") {
e.preventDefault();
}
}
CODEPEN
You're having the parameters in the method wrong. The are 2 ways this can go using the #change event handler:
A
defining a change handler without arguments, like
<el-radio-group #change="changeHandler" v-model="radio1" ></el-radio-group>
changeHandler(e) {
// e will be the Event object
console.log(e)
}
B
defining a change handler with arguments, put in $event to still include the event object
<el-radio-group #change="changeHandler($event, 'string')" v-model="radio1" ></el-radio-group>
changeHandler(e, value) {
// e will be the Event object
console.log(e);
// value will be 'string'
console.log(value);
}

How to open and close a modal within a child component using a prop, vuejs?

I currently have the following child component
<Edit
#fetchInfo="fetchInfo"
:agencyData="agency"
:dialogEdit.sync="dialogEdit"
></Edit>
Which basically contains a modal
initially it is false, so as not to show the modal:
data(){
return {
dialogEdit: false
}
}
by a method I do:
open(){
this.dialogEdit = true;
}
In my <Edit></Edit> component I have:
<el-dialog title="Editar" :visible.sync="dialogEdit" width="60%">
</el-dialog>
and received with prop:
props: ["dialogEdit"],
But then when closing the modal from the child component I receive an error
[Vue warn]: Avoid mutating a prop directly since the value will be
overwritten whenever the parent component re-renders. Instead, use a
data or computed property based on the prop's value. Prop being
mutated: "dialogEdit"
First of all, apparently you are using Element UI.
But, as the error suggests, you are modifying dialogEdit directly. When closing the element ui modal by clicking the X, dialogEdit becomes false. You could solve this using computed property, like suggested for example in this answer.
Since you are using Element UI you also have another possibility to solve this. The dialog has the event before-close which is fired before the modal is closed. There you can emit the new boolean value for dialogEdit to the parent. So keep the :dialogEdit.sync="dialogEdit" in child tag and add the before-close to the dialog and a function to handle, where you emit the new false value:
<el-dialog title="Editar" :before-close="handleClose" ....>
JS:
methods: {
handleClose() {
this.$emit('update:dialogEdit', false);
}
},
If you have some button in your modal to close the modal, you can add the same function there:
<el-button type="primary" #click="handleClose">Close</el-button>
SANDBOX
quite hard to understand your question. you should elaborate more.
is all this in the same file? if in that case you no need to create a props as there's already dialogEdit in the data() section.
props value is never redefined so if this is the cases, just remove the props.
if that's not solved your problem please update your question with better explaination because i just see one file.

Run method when Vuetify dialog is opened

I have a v-data-table and the user can click on any row and a dialog opens. Inside on my vuetify dialog is a dropdown of data.
I want to filter this data everytime the user clicks on a row and filter out what the user clicked from the dropdown inside the dialog.
Here is my dialog:
<v-dialog v-model="edit" max-width="1200" #input="closeDialog()">
<editCompany :isEdit="true"
v-if="showEdit"
:company="selected"
:adminEdit="true"></editCompany>
</v-dialog>
You can see I'm passing in the values from the table row the user clicked.
Now, I need to use the value being passed in to filter the dropdown. The mounted event only runs once, so my logic inside of it only fires for the first row clicked.
Here is the mounted event inside of my editCompany template:
mounted: async function () {
this.filterOutResults(); //this is where i do my filtering and it works
},
Every other row the user clicks doesn't fire mounted, so I cant use that unless I can unmount the dialog when its closed.
I found how to fire an event when the dialog closes, but I cannot find a vuetify open event.
How do I run a function everytime the dialog opens so I can filter the results or how do I unmount the dialog everytime it closes, so the mounted event can run everytime? Thanks
For future references, I'll expand #mynd comment, which should be the answer:
export default {
data() {
return {
dialogVisible: false,
},
},
watch: {
dialogVisible(visible) {
if (visible) {
// Here you would put something to happen when dialog opens up
console.log("Dialog was opened!")
} else {
console.log("Dialog was closed!")
}
}
},
<v-dialog v-model="dialogVisible" max-width="1200" #input="closeDialog()">
<!-- Add code here, according to Vuetify docs -->
</v-dialog>
For further information (about constructing the v-dialog component itself), refer to the official docs
if you want to do something inside the dialog component when it's open, there is a little workaround that you can do.
<v-dialog v-model="edit" max-width="1200" #input="closeDialog()">
<editCompany :isEdit="true"
v-if="showEdit"
:company="selected"
:dialogOpen="edit"
:adminEdit="true"></editCompany>
</v-dialog>
as you see you can pass dialog's handler variable as dialog's parameter. its 'dialogOpen' in this case.
then inside editCompany component,
watch: {
'dialogOpen' :{
handler(newVal, oldVal) {
//do your stuff.
},
deep: true
},
}
So in short it will watch the variable which is controlling dialog, based on its value which mostly is true or false, you can do your operation.

How to get Vuetify checkbox event.target.checked and event.target.value?

How to get Vuetify checkbox event.target.checked and event.target.value?
I'm using Vuetify's checkbox in my app. When the user checks/unchecks it, I want to get the checked and the value properties.
I realize that it is not a native checkbox element, so I don't have access to event.target.checked or event.target.value, but surely there must be a way to do that. I tried the following:
<p v-for="(linkType, index) in linkTypes" v-if='linksLoaded'>
<v-checkbox
color="info"
:label="linkType"
:value="linkType"
v-model="checkedLinks"
#click="onCheckboxClicked($event)"></v-checkbox>
</p>
...
onCheckboxClicked: function(e) {
console.log(e);
},
For some reason it printed a mouse event TWICE and the checkbox itself didn't change (the check mark wasn't unchecked).
#click.native printed the same mouse event, but once.
I tried #change="onCheckboxClicked" - that printed the v-model.
So is there a way to do that?
I see that you are looping without binding a key, and inside you have v-model which is hooked to a single variable. So, whenever some checkbox is changed all others will update simultaneously. So you need new v-model for each checkbox. Why not add another property in linkTypes so you can v-model="linkType.checked".
change is the name of the event which gets triggered whenever checkbox value is changed and value is passed as a parameter.
<v-checkbox
#change="checkboxUpdated"
color="info"
:label="linkType"
:value="linkType"
v-model="checkedLinks"
#click="onCheckboxClicked($event)"></v-checkbox>
and in methods you need
checkboxUpdated(newValue){
console.log(newValue)
}
The easy way to access whether the checkbox is checked or not after clicking is to check it value. If it is null or empty array, then you can assume that its not checked. It depends on how you initialised the variable. This is the safest way to get what you want.
<v-checkbox
v-for="(el, index) in checkboxes"
:key="index"
v-model="checkbox[index]"
:value="el"
:label="`Checkbox ${index}`"
#change="valueChanged($event, index)"
></v-checkbox>
new Vue({
el: '#app',
data () {
return {
checkboxes: ['Opt 1', 'Opt 2', 'Opt 3', 'Opt 4'],
checkbox: [],
}
},
methods: {
onChange(val, i) {
console.log(val, i, this.checkbox)
if (val === null || val.length === 0) { // Custom checks in this
console.log('Unchecked')
} else {
console.log('Checked')
}
}
}
})
If you really need access to the element, then you can use ref to get the component. Then try to find the input element inside the component. And then find the checked value of that input element. But depending on how the library is implemented, you might not get the right value for $refs.checkbox.$el.target.checked.
You are lookin for a event. If you want to know if your checkbox is checked or not, you should use this:
onCheckboxClicked: function(e) {
console.log(e.target.checked)
},
As you've already noticed, Vuetify checkbox is not a native checkbox element. Therefore, event.target.checked and event.target.value do not exist. To fix this, one needs to do 2 things:
Disable the ripple effect of the v-checkbox. Otherwise, there will be a div on top of the input checkbox tag. Then, event.target is the one we expected.
However, when the user clicks on the label, it also affects the checkbox. In this case, we need to access the checkbox via event.target.control.
The checkbox in your question should like this:
<v-checkbox
color="info"
:ripple="false"
:label="linkType"
:value="linkType"
v-model="checkedLinks"
#click.native="onCheckboxClicked"
/>
Then, in the onCheckboxClicked method:
const onCheckboxClicked = (event) => {
const target = event.target.control ?? event.target;
const isChecked = target.checked;
const value = target.value;
// Do something here...
};
Notice that we use .native modifier for the click event. Otherwise, the event.target.control.checked will give opposite values (false when the checkbox is checked and vice versa).
And small note: you should always bind the key value when using v-for.

Vue wrapper example

There are a good examples of integrating vue with select2.
I have a question.
If we look at this part of the code:
mounted: function () {
var vm = this
$(this.$el)
// init select2
.select2({ data: this.options })
.val(this.value)
.trigger('change')
// emit event on change.
.on('change', function () {
vm.$emit('input', this.value)
})
}
I don't understand, why when we change value of select2, this.value changes too.
I expected a record like:
.on('change', function () {
this.value = $(this.$el).val()
vm.$emit('input', this.value)
})
It behaves that way because of how v-model works. What you are a looking at is a 2-way binding. Where if the value of selected in v-model="selected" changes, the value will be pushed down to the component.
When vm.$emit('input', this.value) is called, it tells the parent to update whatever variable is listening to changes, in this case selected, which it turn gets pushed back to the component such that its value gets changed.
To make it simpler to understand, this is the sequence of events:
select2's value changes
the select2 value change triggers an event emission
the parent receives the event and updates selected
the component's value gets assigned to the new value of selected
the watcher for the value gets triggered and updates select2 with the new value
Good question though.
Caveat: Doing this is understandably poor practice. It will break it sad ways when used with 1-way bindings.
After writing my previous answer, I realized I missed something important: contexts.
On line 5 in the jsfiddle, there is this line:
var vm = this, why?
This is because later on, when doing vm.$emit, this.$emit will not work; the context has been changed.
.on('change', function () {
//this = select2 element
vm.value // == 1
this.value // == 2
vm.$emit("input", this.value);
})
The value on the emit event is not that of the component, but of the select2 element.
While the value has not yet been changed on the component, the new value has been broadcasted to the parent.
Notice how select2 component used in the template:
<select2 :options="options" v-model="selected">
<option disabled value="0">Select one</option>
</select2>
In Vue.js using v-model with components could be simplified to:
<your-component
:value="selected"
#input="value => { selected = value }">
</your-component>
So every time you emit an event from your component the value gets changed at the parent component.
Source