Bootstrap Vue modal causing page jump on close / safari issue - javascript

When I close my bootstrap vue modal it causes a page jump to the section that has the open modal triggers which is fine. In Safari it is jumping well above the section where the triggers are. Is there a way to add a prevent default or similiar that will stop the page jumping when the modal is closed?
<template>
<b-modal
:visible="visible"
size="lg"
centered
#hidden="closeModal"
hide-footer
>
<p>
modal body
</p>
<template>
<div class="w-100">
<b-button
class="btn btn-icon"
#click.prevent="closeModal"
>
<span class="l-btn float-left">
<span class="btn-text">Cancel</span>
<i class="btn-icon-symbol"></i>
</span>
</b-button>
<a
:href="$store.state.modals.interstitial.href"
target="_blank"
class="btn btn-icon btn-icon-arrow"
>
<span class="l-btn float-left">
<span class="btn-text text-white">OK</span>
<i class="btn-icon-symbol text-white"></i>
</span>
</a>
</div>
</template>
</b-modal>
</template>
<script>
import { BButton } from 'bootstrap-vue';
export default {
name: 'Modal',
components: {
'b-button': BButton,
},
computed: {
visible() {
return this.$store.state.modals.interstitial.show;
},
},
methods: {
closeModal() {
this.$store.commit('modals/setShowModal', false);
this.$store.commit('modals/setModalHref', '');
},
},
};
</script>

Related

Buefy modal Close button in header

everyone!
I have modal window on Buefy. This modal open when call method:
onEditHandler(selectedPlan) {
const Component = Vue.extend(Plan);
this.$buefy.modal.open({
parent: this,
component: Component,
hasModalCard: true,
trapFocus: true,
scroll: 'keep',
ariaModal: true,
customClass: 'dialog',
canCancel: 'x',
props: {
isActive: true,
plan: selectedPlan,
roles: this.roles,
plans: this.data,
},
events: {
submit() {
},
close() {
},
},
});
}
Plan contains code:
<template>
<validation-observer v-slot="{ handleSubmit }" ref="contactObserver">
<div class="modal-card">
<header class="modal-card-head">
<h2 class="modal-card-title">Name</h2>
</header>
<section class="modal-card-body">
<validation-provider v-slot="{ errors }" rules="required">
<b-field label="Name"
:type="{ 'is-danger': errors.length }"
:message="errors + [ ' ' ]">
<b-input v-model="name"></b-input>
</b-field>
</validation-provider>
</section>
<footer class="modal-card-foot">
<button class="button" type="button" #click="cancel">Cancel</button>
<button class="button is-success"
#click="handleSubmit(submit)">Update</button>
</footer>
</div>
</validation-observer>
</template>
<script>
</script>
In Result open modal who has close button in right top corner (the image pinned in message)
Main question: How do I move the close btn to the modal window?
Thank's for answers
Modal dialog
You can add a close button on the modal's header like this:
...
<header class="modal-card-head">
<h2 class="modal-card-title">Name</h2>
<button type="button" class="delete" #click="handleCancel" />
</header>
...
And there is method handleCancle() for exmaple:
handleCancel: function() {
this.$refs.contactObserver.reset();
this.$parent.close();
},
I solved problem so:
onEditHandler(selectedPlan) {
const Component = Vue.extend(Plan);
this.$buefy.modal.open({
parent: this,
component: Component,
hasModalCard: true,
trapFocus: true,
scroll: 'keep',
ariaModal: true,
customClass: 'card-form-modal',
canCancel: ['outside'],
props: {
plan: selectedPlan,
roles: this.roles,
plans: this.data,
},
events: {
submit() {
},
close() {
}
},
});
this.changeModalPosition();
}
and Plan contains
<template>
<validation-observer v-slot="{ handleSubmit }" ref="contactObserver">
<div class="modal-card">
<header class="modal-card-head">
<h2 class="modal-card-title">Name</h2>
<button class="modal-close is-large" #click="$emit('close')"></button>
</header>
<section class="modal-card-body">
<validation-provider v-slot="{ errors }" rules="required">
<b-field label="Name"
:type="{ 'is-danger': errors.length }"
:message="errors + [ ' ' ]">
<b-input v-model="name"></b-input>
</b-field>
</validation-provider>
</section>
<footer class="modal-card-foot buttons is-right">
<button class="button" type="button" #click="cancel">Cancel</button>
<button class="button is-success"
#click="handleSubmit(submit)">Update</button>
</footer>
</div>
</validation-observer>
And screenshot
a comment that helped to understand
enter link description here

close the menu if I click on another menu vuejs

I use a component menu and this is displayed for each item but it all stays open if I don't click on close out I would like it to close when I click on another item with a menu.
to open and close I use a toggle on click the component has several styles
i on vuejs 3
I have the impression that each menu is independent so I don't know what to do
<nav role="navigation" :id="uuid">
<div class="app-menu">
<div class="menu-princ" #click.stop="showModal = !showModal">
<span
#click.stop="showModal = !showModal"
v-if="ellipsis"
:class="{ ellipsis: ellipsis, cells: cells }"
></span>
<span #click.stop="showModal = !showModal" v-if="ellipsis === false"
><b></b
></span>
</div>
<div
id="menu-princ"
class="menu-modal"
:class="[{ open: showModal }, { menuEllipsisPosition: ellipsis }]"
v-if="showModal"
>
<div class="wrap">
<header class="menuHeader" :class="{ ellipsisMenu: ellipsis }">
<h6
:class="{ ellipsisTitle: ellipsis, ellipsisTitleAfter: ellipsis }"
>
{{ titleMenu }}
</h6>
<u :class="{ ellipsisSubTitle: ellipsis }">{{ subTitleMenu }}</u>
<button
class="detailBtn"
:class="{ ellipsisDetailBtn: ellipsis }"
#click.stop="showModal = !showModal"
></button>
</header>
<section>
<ul v-if="disableMenuLi">
<li
#click.stop="showModal = !showModal"
v-for="([key, value], j) in Object.entries(items)"
:key="`item${j}`"
:data-label="value.label"
class="menuLiContent"
:class="{
ellipsisBorderBottom: ellipsis,
ellipsisMenuLiContent: ellipsis,
ellipsisliHover: ellipsis,
disable: disable
}"
>
<slot #click.stop="showModal = !showModal" :item="value">{{
item[key]
}}</slot>
</li>
</ul>
</section>
</div>
</div>
</div>
</nav>
</template>
<script>
import { uuid } from 'vue-uuid';
export default {
name: 'Menu',
data() {
return {
showModal: false,
uuid: uuid.v4()
};
}
};
</script>
<style lang="scss" src="./style.scss" scoped></style>

Vue Router only applies active class once and not again

WORKAROUND FOUND, SEE EDIT4
my router is acting a bit funny.
It works perfectly for the first link you click, however It doesn't apply the active class after the first time, if I refresh the page it will apply. you can see in the gif here:
Here is my navigation bar code:
<template>
<div class="nav">
<div class="nav__logo-box">
<img src="/logo-no-text-morning.png" :class="$mq" alt />
</div>
<div class="nav__nav-list">
<div class="nav__link">
<router-link to="/" exact-active-class="active-page">
<i class="fas fa-horse-head fa-3x"></i>
<p>Home</p>
</router-link>
</div>
<div class="nav__link">
<router-link to="/about" exact-active-class="active-page">
<i class="fas fa-info-circle fa-3x"></i>
<p>About</p>
</router-link>
</div>
<div class="nav__link">
<router-link to="/gallery" exact-active-class="active-page">
<i class="fas fa-images fa-3x"></i>
<p>Gallery</p>
</router-link>
</div>
<div class="nav__link">
<router-link to="/contact" exact-active-class="active-page">
<i class="fas fa-envelope-open-text fa-3x"></i>
<p>Contact</p>
</router-link>
</div>
</div>
</div>
</template>
Here is my router index.ts
import Vue from "vue"; import VueRouter, { RouteConfig } from "vue-router"; import Home from "../views/Home.vue"; Vue.use(VueRouter); const routes: Array<RouteConfig> = [ {
path: "/",
name: "Home",
component: Home }, {
path: "/about",
name: "About",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import("#/views/About.vue") }, {
path: "/contact",
name: "Contact",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import("#/views/Contact.vue") }, {
path: "/gallery",
name: "Gallery",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import("#/views/Gallery.vue") } ]; const router = new VueRouter({ routes }); export default router;
EDIT:
here's the a look at the web browser debugger:
It for some reason is adding an router-link-active to the home page (probably because its path is just "/").
And then it will add the exact-active just once, but then clicking on another page it will not change. it will stay on the page you was on before, only way to make it change is to refresh the page.
EDIT2:
So now I have decided to store the current page using the following code:
methods: {
getCurrentPage: function() {
this.currentPage = this.$router.currentRoute.name;
}
},
However you can see the behaivour here, it again doesn't update properly and lags behind, it's maybe one or two pages behind where I actaully am.
EDIT3:
I have tried to use a computed method to watch instead but it does not update, it just gets the first page its on and doesnt update again.
data: function() {
return {
currentPage: ""
};
},
computed: {
getCurrentPage: function() {
return this.$router.currentRoute.name;
}
},
mounted() {
console.log(this.$router.currentRoute.name);
this.currentPage === this.getCurrentPage;
}
EDIT4: (WORKAROUND FOUND)
So with the help of the comments, I've got a workaround that will work for now. it's this:
computed: {
getCurrentPage: function() {
return this.$route.name;
}
}
On the links I then bind the active page class:
<div class="nav__nav-list">
<div class="nav__link">
<router-link to="/" :class="{ currentpage: getCurrentPage === 'Home' }">
<i class="fas fa-horse-head fa-3x"></i>
<p ref="homeLink">Home</p>
</router-link>
</div>
<div class="nav__link">
<router-link to="/about" :class="{ currentpage: getCurrentPage === 'About' }">
<i class="fas fa-info-circle fa-3x"></i>
<p ref="aboutLink">About</p>
</router-link>
</div>
<div class="nav__link">
<router-link to="/gallery" :class="{ currentpage: getCurrentPage === 'Gallery' }">
<i class="fas fa-images fa-3x"></i>
<p ref="galleryLink">Gallery</p>
</router-link>
</div>
<div class="nav__link">
<router-link to="/contact" :class="{ currentpage: getCurrentPage === 'Contact' }">
<i class="fas fa-envelope-open-text fa-3x"></i>
<p ref="contactLink">Contact</p>
</router-link>
</div>
</div>

Toggle modal dialog from parent component in VUE

So i want to toggle my modal dialog from parent component and i tried each step mentioned here Stack Overflow Question about same Topic , but still my Modal Dialog is not visible and it even has undefined value when i see from VUE console. and in Elements section the modal dialog div is not created.
MY MODAL DIALOG is not showing in elements section on webpage, but showing in Vue console with undefined prop value. But Click effect is working from Parent component. and modal is setting true when i click on div.
My Parent Code
<template>
<div class="collection">
<section class="section section-elements">
<div class="elements-outer" #click="openModal">
<CopyComponent v-bind:item="item"/>
</div>
</section>
<modal v-modal="modal"/>
</div>
</template>
<script>
import Modal from "../components/Modal.vue";
export default {
name: 'Collection',
components: {
Modal
},
data() {
return {
modal: false
}
},
methods: {
openModal() {
this.modal = !this.modal;
}
}
}
</script>
My Child Component
<template>
<div v-if="value" class="modal">
<div class="body">
body
</div>
<div class="btn_cancel" #click="modalToggle">
<i class="icon icon-cancel" />
</div>
</div>
</template>
<script>
export default {
name: "Modal",
props: ["value"],
methods: {
modalToggle() {
this.$emit("input", !this.value);
}
}
};
</script>
am i missing anything?
Please help, thanks.
Your prop is called value so you need to pass it from parent component, also assign event for toggle modal.
<modal :value="modal" #toggle="modalToggle"/>
And in your child:
<template>
<div v-if="value" class="modal">
<div class="body">
body
</div>
<div class="btn_cancel" #click="modalToggle">
<i class="icon icon-cancel" />
</div>
</div>
</template>
<script>
export default {
name: "Modal",
props: ["value"],
methods: {
modalToggle() {
this.$emit("toggle");
}
}
}
</script>
You misspelled v-model in <modal v-modal="modal"/>, it should be <modal v-model="modal"/>

el-popover in a v-for, open only one popover per line

I try to open a popover when I click on the "Delete" button.
The problem is that all the popovers of all the "Delete" buttons open at the same time.
Can you help me solve this problem?
I would like the click, only the popover concerned opens. And with the button "cancel", only the button concerned closes.
Thank you !
<template>
<div>
<div v-for="student in students.data">
<div class="col--10">
<avatar v-bind:username="student.name" :size="36" class="col--10"></avatar>
</div>
<div class="t20 col--30">{{ student.name }}</div>
<div class="t20 col--40">{{ student.email }}</div>
<div style="text-align: right" class="col--20">
<el-button icon="el-icon-edit" size="small" #click="editStudent(student)"></el-button>
<el-popover placement="top" width="160"
v-model="deleteStudentPopover">
<p>Are you sure to delete this?</p>
<div>
<el-button size="mini" type="text" #click="deleteStudentPopover = false">cancel</el-button>
<el-button type="primary" size="mini" #click="myDeleteFunction">Yes, delete!</el-button>
</div>
<el-button slot="reference" #click="deleteStudentPopover = true">Delete</el-button>
</el-popover>
</div>
</div>
</div>
</template>
export default {
data() {
return {
deleteStudentPopover: false,
students: []
}
},
}
Use <div v-for="(student, index) in students.data"> then bind/pass index when calling different functions.

Categories

Resources