Why V-Dialog wont show up? - vue.js

I'm trying to figure out why the V-Dialog wont popout and when im trying to click the button, the v-dialog should pop out but it didnt, and this is the error i got
[object Error]:
{description: "'ShadowRoot' is not defined",
message: "'ShadowRoot' is not defined",
number: -2146823279,
stack: "ReferenceError: 'ShadowRoot' is not defined at
handleShadow (eval code:33314:3) at
inserted (eval code:33334:5) at
callHook$1 (eval code:6714:7) at
callInsert (eval code:6653:9) at
wrappedHook (eval code:2243:5) at
invokeWithErrorHandling (eval code:1862:5) at
invoker (eval code:2183:9) at
invokeInsertHook (eval code:6380:9) at
patch (eval code:6599:5) at
Vue.prototype._update (eval code:3957:7)"}
and here are the code :
html
<div>
<v-data-table
:headers="headers"
:items="data"
class="elevation-1"
hide-default-footer
>
<template v-slot:[`item.action`]="{ item }">
<v-btn depressed #click="view(item.book_id)" color="primary">View</v-btn>
</template>
</v-data-table>
<v-text-field v-model="ItemPerPage" label="Items Per Page" #change="GettingDataPerItem">
</v-text-field>
</div>
<v-dialog v-model="dialog" max-width="800px">
<v-card>
<v-card-title>
<span class="subtitle-1 font-weight-bold">Details Of Book</span>
</v-card-title>
<v-form lazy-validation>
<v-col cols="12" align-self="center">
<v-layout wrap justify-center>
<v-flex d-flex lg5 sm5 xs12>
<v-text-field v-model="book_id" :readonly="true" class="allText" label="Book ID"/>
</v-flex>
<v-divider class="mx-4" vertical/>
</v-layout>
</v-col>
<v-card-actions>
<v-layout v-if="IsActive === 0" justify-end class="ma-4">
<div>
<v-btn #click="dialog = false" style="width:150px;margin-left:10px" color="#263238" class="white--text">Close</v-btn>
</div>
</v-layout>
</v-card-actions>
</v-form>
</v-card>
</v-dialog>
When i read the code like over 20 times, it looks fine with me, and read the script over and over and nothing wrong to me
script
export default {
data() {
return {
dialog: false,
//censored_code
};
},
view(emp_no) {
this.$axios
.$post(`some/api/.......`, {
book_id: book_id,
})
.then((res) => {
//result of the respond data
this.dialog = true
});
},
},
This ShadowRoot annoyed me, how to fix this? should upgrade something?

Make sure your <v-data-table> and <v-dialog> elements are contained within a single root:
<template>
**<something>**
<div><v-data-table></v-data-table></div>
<v-dialog/>
**</something>**
</template>

Finally solve the problem, i'm using microsoft edge and then switch to firefox and the v-dialog poped out

Related

v-slot:badge and v-if does not work with a computed property

I'm working on a CMS project and I have an issue I can't figure out.
I Have a component where I'm showing IP's. On change I want a badge to appear, so the user knows "this field is changed".
But the thing is the badge won't show if I'm using "v-slot:badge".
In the v-if is a computed property, If I inspect the page with vue devtools ‘isStartIpValueChanged’ will be true on a change. So, it should work right?
Template
<v-list-item-content>
<v-form ref="form" v-model="valid">
<v-hover v-slot:default="{ hover }">
<v-row align-content="center" no-gutters>
<v-col>
<v-badge overlap color="red" right>
<template v-slot:badge v-if="isStartIpValueChanged">
<v-avatar color="red" size="6"></v-avatar>
</template>
<v-text-field
dense
:rules="apiIpRules"
v-model="apiIp.startIp"
#input="valueChanged()"
ref="startIp"
:class="hover ? 'hover-text-color' : ''"
placeholder="###.###.###.###">
</v-text-field>
</v-badge>
</v-col>
<v-col cols="1" class="text-center" align-self="center">
<p>-</p>
</v-col>
<v-col cols="1" class="text-center" align-self="center">
<v-btn v-show="hover" #click="deleteIp()" icon small color="red"><v-icon>mdi-minus-circle</v-icon></v-btn>
</v-col>
</v-row>
</v-hover>
</v-form>
Created and Computed (apiIp is a prop I get from the parent component)
created () {
this.apiIpsOriginalValueStartIp = this.apiIp.startIp
this.apiIpsOriginalValueEndIp = this.apiIp.endIp
this.apiIp.uuid = this.GenerateUUID()
},
computed: {
isStartIpValueChanged () {
return this.apiIp &&
(this.apiIp.startIp !== this.apiIpsOriginalValueStartIp ||
this.apiIp.uuid === null)
},
isEndIpValueChanged () {
return this.apiIp &&
(this.apiIp.endIp !== this.apiIpsOriginalValueEndIp ||
this.apiIp.uuid === null)
}
},
Anyone know what is going wrong here?
As according to Vuetify's own documentation, you should be using the v-model, directly on the v-badge, to show it only when you want it to.
<v-badge overlap color="red" right v-model="isStartIpValueChanged">
<template v-slot:badge>
<v-avatar color="red" size="6"></v-avatar>
</template>
<v-text-field
dense
:rules="apiIpRules"
v-model="apiIp.startIp"
#input="valueChanged()"
ref="startIp"
:class="hover ? 'hover-text-color' : ''"
placeholder="###.###.###.###">
</v-text-field>
</v-badge>
Doc: https://vuetifyjs.com/en/components/badges#show-on-hover

Datepicker doesn't get validated on input

I'm currently using the datepicker component in one of my projects. The component is supposed to throw an error message if I click in and out of the empty textfield of the datepicker menu. So far the error message only works if I enter a value and then remove it again.
There are already rules which check if the date-value of the textfield is longer than 0 Digits or not null.
HTML
<div id="app">
<v-app id="inspire">
<v-container grid-list-md>
<v-form v-model='validForm'>
<v-layout row wrap>
<v-flex xs12 lg6>
<v-text-field
v-model="text"
clearable
label="Regular Textfield"
:rules="rulesDatefield"
v-on="on"
></v-text-field>
<v-menu
v-model="menu1"
:close-on-content-click="false"
full-width
max-width="290"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model='date'
clearable
label="Datefield"
readonly
:rules="rulesDatefield"
v-on="on"
></v-text-field>
</template>
<v-date-picker
v-model="date"
#change="menu1 = false"
></v-date-picker>
</v-menu>
</v-flex>
</v-layout>
</v-form>
<v-btn :disabled="!validForm" #click='printValues()' color='primary'>Create</v-btn>
</v-container>
</v-app>
</div>
JS
new Vue({
el: '#app',
data: () => ({
validForm: false,
text: '',
date: '',
menu1: false,
rulesDatefield: [
v => String(v).length > 0 || 'Field is empty!',
v => v !== null || 'Field is empty!'
]
}),
methods: {
printValues: function() {
window.alert('Entered Text: ' + this.text + '\nEntered Date:' + this.date)
}
}
})
Codepen: https://codepen.io/anon/pen/XLLNZM?&editable=true&editors=101
I expect an error message from the date-textfield like in the regular textfield above if I enter and exit the datepicker without selecting a date.
<v-text-field
v-model="date"
clearable
readonly
label="Datefield"
:rules="rulesDatefield"
v-on="on"
#blur="date = date || null"
></v-text-field>
Seems strange but works, as you intended.

Vue.js How to set scroll position back to top?

So whenever I click the "edit" button, a dialog pops up with a scrollbar where I can fill out information. But when I click "cancel" or "save" and then click that same "edit" button, the dialog pops up at the same scroll position. I would like to, every time when I click "edit" and the dialog opens up, be always at the top of the dialog page not where I left off last.
<template>
<!-- <div class="text-xs-center" v-if="storeState.admin" lazy> -->
<v-dialog
transition="dialog-bottom-transition"
scrollable
fullscreen
v-model="sheet"
v-if="storeState.admin"
lazy
persistent
>
<template v-slot:activator="{on}">
<v-btn flat color="green" dark icon v-on="on">
<v-icon>edit</v-icon>
</v-btn>
</template>
<div background-color="transparent" style="margin: auto auto 0 auto">
<v-card px-5 max-width="800px">
<v-card-title>
ADD SCHOLARSHIP
</v-card-title>
<v-form v-model="addDisabled" validation ref="editForm">
<v-container>
<v-layout wrap>
<v-flex
xs12
md4
>
<v-text-field
v-model="scholarship.title"
label="Scholarship name"
:counter="maxLength"
:rules="[maxLength_rules.max, minLength_rules.min]"
required
></v-text-field>
</v-flex>
<v-flex xs12 md4>
<v-text-field
v-model="scholarship.faculty"
label="Faculty"
:counter="maxLength"
:rules="[maxLength_rules.max, minLength_rules.min]"
required
></v-text-field>
</v-flex>
<v-flex xs12 md4>
<v-text-field
v-model="scholarship.dollarAmount"
label="Award amount"
required
:rules="[amount_rules.range, minLength_rules.min]"
></v-text-field>
</v-flex>
<v-flex ml-2 xs12 sm6 md4>
<v-menu
ref="menu2"
v-model="menu2"
:close-on-content-click="false"
:nudge-right="40"
:return-value.sync="availableDate"
transition="scale-transition"
offset-y
full-width
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="scholarship.available"
label="Date Available"
prepend-icon="event"
:rules="[minLength_rules.min]"
readonly
v-on="on"
></v-text-field>
</template>
<v-date-picker v-model="availableDate" no-title scrollable>
<v-spacer></v-spacer>
<v-btn flat color="primary" #click="menu2 = false">Cancel</v-btn>
<v-btn flat color="primary" #click="$refs.menu2.save(availableDate)">OK</v-btn>
</v-date-picker>
</v-menu>
</v-flex>
<v-flex ml-2 xs12 sm6 md4>
<v-menu
ref="menu1"
v-model="menu1"
:close-on-content-click="false"
:nudge-right="40"
:return-value.sync="dueDate"
transition="scale-transition"
offset-y
full-width
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="scholarship.deadline"
label="Due Date"
prepend-icon="event"
readonly
:rules="[minLength_rules.min]"
v-on="on"
></v-text-field>
</template>
<v-date-picker v-model="dueDate" no-title scrollable>
<v-spacer></v-spacer>
<v-btn flat color="primary" #click="menu1 = false">Cancel</v-btn>
<v-btn flat color="primary" #click="$refs.menu1.save(dueDate)">OK</v-btn>
</v-date-picker>
</v-menu>
</v-flex>
<v-flex xs12 md1>
<v-text-field
v-model="scholarship.requiredGpa"
label="Min GPA"
required
:rules="[gpa_rules.range, minLength_rules.min]"
></v-text-field>
</v-flex>
<v-flex xs12>
<v-textarea
outline
height="400"
v-model = "scholarship.description"
label="Scholarship Description"
:rules="[minLength_rules.min]"
></v-textarea>
</v-flex>
</v-layout>
</v-container>
</v-form>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn flat #click="sheet = false" >cancel</v-btn>
<v-btn color="primary" #click="updateFields(scholarship)" :disabled="!addDisabled" flat >SAVE</v-btn>
</v-card-actions>
</v-card>
</div>
</v-dialog>
<!-- </div> -->
</template>
<script>
import { store } from "../store.js";
import EDITSCHOLARSHIP from '../graphql/updateScholarship.gql'
export default {
data: () => ({
sheet: false,
valid: false,
dueDate: '',
availableDate: '',
storeState: store.state,
addDisabled: true,
menu1: '',
menu2: '',
gpa: '',
title: '',
faculty: '',
amount: '',
maxLength: 255,
description: '',
gpa_rules: {
range: v => v <= 4.00 && v >= 0.00 && v.length <=4 || 'GPA may only be within 0.00 - 4.00',
},
amount_rules: {
range: v => v <= 999999999.00 && v >= 0.00 || 'Amount must only contain numbers between 0.00 - 999999999.00',
},
maxLength_rules: {
max: v => v.length <= 255|| 'Max character length is 255',
},
minLength_rules: {
min: v => v.length > 0 || 'Required',
}
}),
props: {
scholarship: Object
},
methods: {
validate () {
if (this.$refs.editForm.validate()) {
this.addDisabled = false
}
},
editScholarship(scholarship) {
if (this.$refs.editForm.validate()) {
this.$apollo.mutate({
mutation: EDITSCHOLARSHIP,
variables: {
id: scholarship.id,
input: {
available: this.availableDate,
deadline: this.dueDate,
description: this.description,
dollarAmount: this.amount,
faculty: this.faculty,
requiredGpa: this.gpa,
title: scholarship.title,
visible: true,
}
}
}).then( (data) => {
this.$emit('showSnackbar', 'Scholarship successfully updated', 'success')
this.sheet = false
}).catch( (error) => {
this.$emit('showSnackbar', 'Scholarship update failed', 'error')
//this.text = error
//this.color = "error"
//this.snackbar = true
})
}
},
updateFields (scholarship) {
this.dueDate = scholarship.deadline
this.availableDate = scholarship.available
this.gpa = scholarship.requiredGpa
this.title = scholarship.title
this.faculty = scholarship.faculty
this.amount = scholarship.dollarAmount
this.description = scholarship.description
this.editScholarship(scholarship)
}
}
}
</script>
<style>
.scroll {
overflow-y: auto;
}
</style>
This is intended behavior. If the dialog box is not removed from the DOM when closed, its previous state will be retained unless otherwise modified.
You can choose one between three approaches I can think of in hindsight, 2 of which are what you are looking for.
Destroy the modal when not in use and re-instantiate when opening. A simple v-if toggling a boolean would do the trick, or a this.$destroy if your dialog box is a separate vue instance.
Add this.$el.scrollTop = 0 on your submit or cancel events. (A*)
Add scrollWrapper.scrollTop = 0 on your open dialog box method. (B*)
A: this.$el on item number 2 will only work if you are scrolling in the $el element, otherwise, you can access the target element using this.$el.querySelector('.scroll-wrapper')
B: Same as item number 2, but this uses vanilla JS references instead of relying on Vue, you should refer to your actual scroll wrapper.
Please add this code to the event to enable in your dialog.
this.$refs.editForm.$el.scrollIntoView({behavior: 'smooth'})

Vue - closing dialog from child component

I'm using Vue and Vuetify and I'm having trouble closing a dialog from within a child component using $emit. In the main component I'm using v:on:close-dialog="closeDialog" and setting this.dialog = false. I'm trying to call that function from within the child. Trying three different ways:
On the <v-icon>close</v-icon> in the child component, I'm calling a closeDialog method that calls this.$emit('close-dialog').
On the <v-btn>Cancel</v-btn>, I have v-on:click="$emit('close-dialog')".
On the <v-btn>Cancel 2</v-btn>, I have v-on:click="$emit('dialog',false)".
None of those close the dialog or fire off the closeDialog method in the main component. Code is below.
mainComponent:
<template>
<v-flex>
<v-flex xs12 class="text-xs-right">
<v-dialog v-model="dialog" fullscreen hide-overlay
transition="dialog-bottom-transition">
<v-btn fab slot="activator" small color="red" dark>
<v-icon dark >add</v-icon>
</v-btn>
<childComponent v:on:close-dialog="closeDialog" />
</v-dialog>
</v-flex>
</v-flex>
</template>
<script>
import childComponent from './childComponent'
export default {
data(){
return{
dialog: false
}
},
name: 'Test',
components: {
childComponent
},
methods:{
closeDialog: function(){
console.log('close dialog 2');
this.dialog = false;
}
}
}
</script>
childComponent:
<template>
<v-flex xs12>
<v-card>
<v-toolbar dark color="primary">
<v-btn icon dark v-on:click="closeDialog">
<v-icon>close</v-icon>
</v-btn>
<v-toolbar-title>Dialog Test</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-btn dark flat v-on:click="$emit('close-dialog')">Cancel</v-btn>
</v-toolbar-items>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-btn dark flat v-on:click="$emit('dialog',false)">Cancel 2</v-btn>
</v-toolbar-items>
</v-toolbar>
<v-flex xs12 class="px-10">
<v-form ref="form">
<v-text-field
v-model="testField"
:counter="150"
label="Test field"
required
></v-text-field>
</v-form>
</v-flex>
</v-card>
</v-flex>
</template>
<script>
export default {
data: () => ({
testField: ''
}),
methods: {
closeDialog: function(){
console.log('close dialog 1');
this.$emit('close-dialog');
}
}
}
</script>
As you might have guessed, I'm new to Vue and still fumbling my way through it. Any help would be much appreciated.
In your parent you have:
<childComponent v:on:close-dialog="closeDialog" />
it should be (hyphen replaces colon in v-on):
<childComponent v-on:close-dialog="closeDialog" />
or #close-dialog altenatively.
This method, combined with this.$emit('close-dialog'); in your child should work.

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();