I'm trying to use Modal Component Example from Vue.js website examples in my project. When I use the modal component in my-project component, it works fine, but when I add a close button in the header slot, this button doesn't work, it doesn't close the modal while the default button in the footer still works fine.
The modal component :
<template>
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
default body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
default footer
<button class="modal-default-button" #click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
props: {
showMal: Boolean
}
}
</script>
<style scoped>
<!-- same as vuejs website modal component example -->
</style>
How I'm calling it :
<template>
<button id="show-modal" #click="showModal = true">Show Modal</button>
<!-- use the modal component, pass in the prop -->
<modal v-if="showModal" #close="showModal = false">
<!--
you can use custom content here to overwrite
default content
-->
<div slot="header">
<button class="modal-default-button" #click="$emit('close')">Close</button>
</div>
</modal>
</template>
<script>
export default {
data () {
return {
showModal: false
}
}
</script>
What's wrong in my implementation of this code ?
Since this is at the parent:
<template>
<button id="show-modal" #click="showModal = true">Show Modal</button>
<!-- use the modal component, pass in the prop -->
<modal v-if="showModal" #close="showModal = false">
<!--
you can use custom content here to overwrite
default content
-->
<div slot="header">
<button class="modal-default-button" #click="$emit('close')">Close</button>
</div>
</modal>
</template>
This code:
<button class="modal-default-button" #click="$emit('close')">Close</button>
Actually makes the parent emit the 'close', not the modal child.
So, since the property that controls the modal is showModal, just set it to false instead:
<button class="modal-default-button" #click="showModal = false">Close</button>
Demo JSFiddle: https://jsfiddle.net/acdcjunior/mwLbw11k/4208/
Related
I started using Laravel with vue.js, i have created some pages using vue.js
so i have modal that i would like to use in both of pages ( page1.vue and page2.vue ) without re write the modal html code again:
Page1.vue
<template>
<div>Page 1 </div>
</template>
Page2.vue
<template>
<div>Page 2 </div>
</template>
How can i share a modal.vue with this two pages
Just import the modal component into both pages. Here ive done it with a bool modalBool that will toggle weather the modal is displayed or not.
<template>
<div>
Page 1
<modal v-if="modalBool"> </modal>
</div>
</template>
<script>
import Modal from "./Modal.vue";
export default {
components: {
Modal,
},
data() {
return {
modalBool: false,
};
},
};
</script>
<style lang="scss" scoped></style>
You can add things like on close to reset the bool in the parent
<template>
<div>
Page 1
<modal v-if="modalBool" v-on:close="showInvitationModal = false"> </modal>
</div>
</template>
Here is an example of my modal that will emit close when closed. The parent is listening for this close and will reset the modalBool. This will be emitted if the user clicks outside of the modal or on the X
<template>
<transition name="component-fade" mode="out-in">
<div class="modal-background" #click.self="$emit('close')">
<div class="modal-body shadow">
<h2 class="modal-title">
<div>{{ title }}</div>
<div>
<button class="btn-clear" #click="$emit('close');">
<font-awesome-icon :icon="timesIcon" class="pointer" />
</button>
</div>
</h2>
<div>
<slot></slot>
</div>
</div>
</div>
</transition>
</template>
I have created a vue single page this way:
My app.vue
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
<div id="app">
<Navegacion/>
<Cabecera/>
<Contenido/>
<Aside/>
<Footer/>
</div>
</template>
My navigation.vue
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
<div class="flex flex-row blanco">
<div class="item-uno">
<nav class="flex flex-row items-center">
<a #click="desplazar" href="#">Quienes somos</a>
<a #click="desplazar" href="#">Cómo funciona</a>
<a #click="desplazar" href="#">Servicios a empresas</a>
<a #click="desplazar" href="#">Compromiso</a>
</nav>
</div>
<div class="item-dos flex justify-center">
<img id="logo" src="../assets/logo.svg" alt="logo apeteat">
</div>
<div class="item-uno flex justify-center items-center">
<a class="btn blue">Nuevo pedido</a>
<div class="flex flex-row items-center">
<i class="fas fa-shopping-bag"></i>
<p>0,00 €</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Navegacion',
props: {
},
methods: {
desplazar: function() {
window.scrollTo(0,200);
}
}
}
</script>
I want to make scroll to the correspondent component when clicking on a navigation link.
I have installed npm scroll-to, and I have tried to add a function methd desplazar but it's not working.
Thanks in advance for your help.
window.scrollTo() is javascript window method, you don't need to install anything to use it.
It works in your code but href="#" always throw you at the top of the page so it's cancelling window.scrollTo().
You need to remove href="#" from your links.
To scroll to component first you need to add ref to it like this:
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
<div id="app">
<Navegacion ref="Navegacion" />
<Cabecera ref="Cabecera" />
<Contenido ref="Contenido" />
<Aside ref="Aside" />
<Footer ref="Footer" />
</div>
</template>
and your function should looks like this
scrollToNavegacion() {
window.scrollTo(0, this.$refs.Navegacion.$el.offsetTop);
}
When I click on the outer area of the modal, I want the same event as the close button of the modal. (Event that closes modal when clicking outside area of modal)
The current progress is that the modal is closed when the close modal button is clicked.
Carousel.vue
<template>
<div>
<div v-for="(item, index) in photos" :key="index">
<div #click="imgClick(item)" style="cursor:pointer;">
<img :src="item.thumbnail" />
</div>
<Modal v-if='item.show' #close="item.show = false">
<div slot='body'>
<img :src="item.thumbnail" :class="`img-index--${index}`"/>
</div>
</Modal>
</div>
</div>
</template>
<script>
import Modal from './Modal.vue'
export default {
props: {
items: { type: Array, default: () => [] }
},
data() {
return {
photos: {}
}
},
created() {
this.photos = this.items.map(item => {
return { ...item, show: false }
})
},
methods: {
imgClick(item) {
item.show = true
}
},
components: {
Modal: Modal
}
}
</script>
Modal.vue
<template>
<transition name="modal">
<div class="modal-mask" #click="$emit('close')">
<div class="modal-wrapper">
<div class="app__phone">
<div class="feed">
<div class="post">
<div class="header headroom">
<div class="level-left">
<img src="../assets/imgs/user.gif" class="modal-header-img"/>
<div class="user">
<span class="username">username</span>
<button class="modal-default-button" #click="$emit('close')">Close</button>
</div>
</div>
</div>
<slot name="modal-img"></slot>
<div class="content">
<div class="content-title">
<slot name="modal-tit"></slot>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</transition>
</template>
When I add a click event to the bottom <div>, it closes when I click outside the modal, but it closes when I click anywhere in the modal.
<div class="modal-mask" #click="$emit('close')">
And this link has a Fiddle example in the accepted answer to the question.
https://stackoverflow.com/a/58023701/12066654
You need to add a handler to the outer modal div like so:
<template id="modal">
<div class="modal" #click.self="close">
<div class="close" #click="close">×</div>
<div class="body">
<slot name="body" />
</div>
</div>
</template>
I am trying to show a modal window as in this example. https://codepen.io/anon/pen/dgRKEP?editors=1010
But for some reason, the modal window is not shown.
<div id="app6">
<div class="has-text-centered">
<button class="button is-success" #click="showModal = true">
show modal!
</button>
</div>
<modal title="Title of the modal" v-show="showModal" #close="showModal = false">
<div class="content">
is modal!
</div>
</modal>
</div>
Script:
Vue.component('modal', {
template: `
<div class="modal is-active">
<div class="modal-background"></div>
<div class="modal-content">
<div class="box"><slot></slot></div>
</div>
<button class="modal-close" #click="$emit('close')"></button>
</div>
`
});
new Vue({
el: '#app6',
data:{
...
showModal: true
...
},
I'm assuming you're using Bulma. So you need to include their stylesheet for things to work correctly. The simplest way is to just use a CDN. So you need to include this line in your head tag or somewhere before your app div.
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css">
Like this for example ..
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css">
<div id="app">
<div id="app" class="container">
<div class="has-text-centered">
<button class="button is-success" #click="showModal = true">
Покажите мне всплывашечку!
</button>
</div>
<modal title="Title of the modal" v-show="showModal" #close="showModal = false">
<div class="content">
</div>
</modal>
</div>
</div>
See this JSFiddle
You need to add the css. you can add your own css or use the library that used in the code pen example: https://cdnjs.cloudflare.com/ajax/libs/bulma/0.2.3/css/bulma.min.css. Clicking the css setting button you will find the imported library.
Is there any way to implement the following carousel in Vue2. Link :
Image Carousel
// Parent component
<div class="col">
<slider>
<slide v-for="intro in compOpts.blockIntro">
<block-intro :compOpts="{ props: { wrapper: true, bg: false } }">
<p v-html="intro.title"></p>
<div slot="content" v-html="intro.content" class="blockIntro__content"></div>
</block-intro>
</slide>
</slider>
</div>
// Slider component
<div class="slider__container">
<slot></slot>
</div>
// Slide component
<div>
<slot></slot>
</div>
// BlockIntro component
<div class="col--h100" :class="{ 'bg--darkDark': compOpts.props.bg, 'col': !compOpts.props.wrapper }">
<div class="col col__blockIntro" :class="{ 'col__blockIntro--spaced': compOpts.props.spaced }">
<div class="col col__blockIntro__introQuote">
<slot></slot>
</div>
<slot name="content"></slot>
</div>
My Slide component is giving me the BlockIntro component template and div.col--h100 is the first/parent child element inside Slider. Now I'm trying to add an visible class to div.col--h100 from the Slider component. I consoled the Vnode using $slots but can't change the value in $slots.$elm.className
Please help.