Vue: Don't close dialog on invalid login - vue.js

I'm a complete beginner to Vue and I have an extremely basic question that is tripping me up.
I have a Dialog that opens up and asks for user input. When the user clicks okay, it makes a call to an API and tries to add the user input to a database. This works fine and I'm able to successfully hit the database. The issue I'm having is if the API doesn't return a 200. I want to persist the dialog and add text that says "Invalid Input. Try again." However, everything I've tried just closes the dialog automatically.
The code I have looks like:
<v-dialog v-model="show" width="500">
<template v-slot:activator="{ on, attrs }">
<v-btn text color="green" v-bind="attrs" v-on="on"> Add User </v-btn>
</template>
<v-card>
<v-card-title class="text-h5 grey lighten-2"> Add User </v-card-title>
<v-spacer></v-spacer>
<v-card-text>
<v-text-field label="User to add" v-model="addUser"></v-text-field>
</v-card-text>
<!-- <v-card-text v-if="successfullyAdded == false"><strong class="red--text text--lighten-1">Please input a valid username</strong></v-card-text> -->
<v-spacer></v-spacer>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="primary"
text
#click="
show = false
addUser(index)
"
>
Add
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
How do I persist a dialog conditionally such that it stays open if addUser returns False and otherwise closes normally?

Related

Instance of v-dialog is generated twice – Vuetify

I have a problem with <v-dialog> that appears everywhere in my Vue.js application using Vuetify.js.
Every <v-dialog> is loading twice on the page. You can see it by looking at how it appears:
If I close one dialog the other dialog stays visible and works exactly like the first. It seems like Vue is generating two instances of it.
The code of the dialog isn't the issue, I think:
<v-dialog
v-model="dialog"
persistent
hide-overlay
no-click-animation
>
<v-card>
<v-card-title>Text</v-card-title>
<v-card-text>
<p class="subtitle-1">Some more text</p>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="primary"
depressed
>
Next
<v-icon right>mdi-chevron-right</v-icon>
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
The v-model is declared in data():
export default {
data() {
return {
dialog: true,
};
},
}
Any help is appreciated! Thanks.

Delete line in Vuetify data-table with delete button in dialog

I have data-table with an edit and delete icon to each line. When using the code below and pressing the delete icon I get a system pop-up and the the line deletes the way I want it. So perfect.
<template v-slot:item.actions="{ item }">
<v-icon small class="mr-2" #click="editItem(item)">mdi-pencil</v-icon>
<v-icon small text #click="deleteItem(item)">mdi-delete</v-icon>
</template>
Methods script:
deleteItem(item) {
const index = this.companies.indexOf(item);
confirm("Are you sure you want to delete this item?") &&
this.companies.splice(index, 1);
},
Now instead of the system pop-up I want to have a nice dialog. Like in https://codepen.io/anon/pen/pYzZPZ?editors=1010.
So I've made this code:
<template v-slot:item.actions="{ item }">
<v-icon small class="mr-2" #click="editItem(item)">mdi-pencil</v-icon>
<v-icon small #click="dialog2 = true">mdi-delete</v-icon>
<v-dialog v-model="dialog2" max-width="500px">
<v-card>
<v-card-title>Verwijderen</v-card-title>
<v-card-text>Weet je zeker dat je {{item.name}} wenst te verwijderen?</v-card-text>
<v-card-actions>
<v-btn color="primary" text #click="dialog2 = false">Close</v-btn>
<v-btn color="primary" text #click="deleteItem(item)">Verwijderen</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
And with Methods script:
deleteItem(item) {
const index = this.companies.indexOf(item);
this.companies.splice(index, 1);
this.dialog2 = false;
console.log("Delete success");
},
I've added the console log to see if the button actually did something.
When I press the delete icon now I do get the dialoge. When I press "close" everything is fine.
When I press delete I get the message "Delete success" in console but the line is not deleting.
When I press the delete button again the page crashes....Any ideas?
The problem is that there are multiple instances of v-dialog bound to dialog2 because it's inside a slot that repeats. This is different than the single instance of window.confirm that works. So, when you attempt to deleteItem(item) the item to delete is always the last in the array.
Put the v-dialog dialog outside the v-data-table, and keep track of the itemToDelete (this same way edit works). Use a method to toggle the dialog and remember the item...
showDeleteDialog(item) {
this.itemToDelete = item
this.dialogDelete = !this.dialogDelete
},
deleteItem() {
console.log('deleteItem', this.itemToDelete)
const index = this.items.indexOf(this.itemToDelete)
this.items.splice(index, 1)
this.dialogDelete = false
},
Then the template is...
<v-data-table>
<template v-slot:item.actions="{ item }">
<div class="text-truncate">
<v-icon
small
class="mr-2"
#click="editItem(item)"
>
mdi-pencil
</v-icon>
<v-icon
small
#click="showDeleteDialog(item)"
>
mdi-delete
</v-icon>
</div>
</template>
</v-data-table>
<v-dialog v-model="dialogDelete" max-width="500px">
<v-card>
<v-card-title>Delete</v-card-title>
<v-card-text>Weet je zeker dat je `{{itemToDelete.Name}}` wenst te verwijderen?</v-card-text>
<v-card-actions>
<v-btn color="primary" text #click="dialogDelete = false">Close</v-btn>
<v-btn color="primary" text #click="deleteItem()">Delete</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
Demo

vuetify: Stop parent animation on click

I have a card which have 2 buttons and I want to have difference function when clicking on:
Card
Button Yes
Button No
I layout the card this way
<v-card
#click.self="$emit('card:clicked')"
>
<v-card-actions>
<v-spacer/>
<v-btn
#click.stop="$emit('btn:yes')"
>
Yes
</v-btn>
<v-btn
#click.stop="$emit('btn:no')"
>
No
</v-btn>
</v-card-actions>
</v-card>
With modifier stop I can emit btn:yes or btn:no event without emit event card:clicked on card, but the clicked animation on card still show and is very confusing.
My question is how I can stop the animation happen like stopping the event card:clicked when I click on the button instead of the card.
After some more search I find out the animation call ripple with vuetify.
With the right words I am able to find the answer at Child and parent ripple triggered
And I can solve my issue by adding #mousedown.stop like below
<v-card
#click.self="$emit('card:clicked')"
>
<v-card-actions>
<v-spacer/>
<v-btn
#click.stop="$emit('btn:yes')"
#mousedown.stop
>
Yes
</v-btn>
<v-btn
#click.stop="$emit('btn:no')"
#mousedown.stop
>
No
</v-btn>
</v-card-actions>
</v-card>

Reset Vuetify form validation

I have trouble resetting vuetify validation in v-dialog.
This codepen is the simplified version of what I have.
https://codepen.io/yuukive/pen/BVqpEZ
With the code above, if I do
(Open dialog --> press SAVE button --> (validation fails) --> press CLOSE button --> open dialog again),
it is already validated when I open the dialog again...
Is it possible to reset validation before a user opens it the 2nd time?
new Vue({
el: '#app',
data: () => ({
dialog: false,
emailRules: [v => !!v || 'Name is required']
}),
methods: {
onSave() {
if (!this.$refs.form.validate()) return
dialog = false
}
}
})
<div id="app">
<v-app id="inspire">
<v-layout row justify-center>
<v-dialog v-model="dialog" persistent max-width="500px">
<v-btn slot="activator" color="primary" dark>Open Dialog</v-btn>
<v-card>
<v-card-title>
<span class="headline">Email</span>
</v-card-title>
<v-form ref="form">
<v-card-text>
<v-container grid-list-md>
<v-layout wrap>
<v-flex xs12>
<v-text-field label="Email" required :rules="emailRules"></v-text-field>
</v-flex>
</v-layout>
</v-container>
<small>*indicates required field</small>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" flat #click.native="dialog = false">Close</v-btn>
<v-btn color="blue darken-1" flat #click.native="onSave">Save</v-btn>
</v-card-actions>
</v-form>
</v-card>
</v-dialog>
</v-layout>
</v-app>
</div>
Example from docs uses:
this.$refs.form.reset()
Note that while reset() clears validation, it clears input as well.
You can follow this issue to see further updates on this.
So you can perhaps watch dialog value and reset the form:
watch: {
dialog() {
this.$refs.form.reset()
}
}
resetValidation() will clear validation errors only, reset() will also clear input fields.
this.$refs.form.reset() might work on JavaScript, but compiler for TypeScript complains about typing. Even though during serve you can only see errors in the terminal without breaking the app, it'll actually break when you'll try to build the app.
Creating a new variable and assigning into it any type does the trick, below an example:
const refForm: any = this.$refs.form;
refForm.reset();

Vuetify component v-form is not responding on the declared #submit event handler

I am using Vuetify and VueJS (the latest versions).
Here is the small template of Login.vue:
<template>
<v-layout align-center justify-center>
<v-flex xs12 sm8 md4>
<v-card class="elevation-12">
<v-toolbar dark color="success">
<v-toolbar-title>Login form</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-card-text>
<v-form #submit.prevent="checkLogin">
<v-text-field prepend-icon="person" id="userLogin" v-model="userLogin" placeholder="my#login.com"></v-text-field>
<v-text-field prepend-icon="lock" id="userPassword" v-model="userPassword" placeholder="password" type="password"></v-text-field>
</v-form>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<!-- TODO fix the bug when form.submit not works -->
<v-btn type="submit" color="success">Login</v-btn>
</v-card-actions>
</v-card>
</v-flex>
</v-layout>
</template>
So, if you see, there is an #submit.prevent on v-form with checkLogin call and it is not working while clicking the submit buttor nor hitting the enter button while in input. Using #submit without prevent also has no effect.
But! If I put event handler on the v-btn like this:
<v-btn #click.native="checkLogin">
after clicking the button (not hitting the enter in input fields) all works as expected.
So, can you please tell me, what am I doing wrong with the v-form submition event handling?
Thank you!
Your submit button isn't inside the form so it's not triggering a submit event.
Either re-structure your markup or try setting an id on the form and use the form attribute on the button, eg
<v-form #submit.prevent="checkLogin" id="check-login-form">
and
<v-btn type="submit" color="success" form="check-login-form">Login</v-btn>
Note: The form attribute does not work for any version of Internet Explorer.