How to render a modal that is inside a component from another component in vueJs and Bootstrap - vue.js

I have a modal inside a Vue component. Now, from another component i want to show that modal(component) when an event happens(click in a button).
This is the code of the component(modal)
This is the component where i want to get the modal
Code of the component with the modal
<template>
<div class="modal fade" id="exampleModal" tabindex="" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modificar Registro Documento</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="false">×</span>
</button>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button data-dismiss="modal" (click)="modificarRegistro()" type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" scoped>
export default {
name : "Modal"
}
</script>
<style lang="sass" scoped>
</style>
This is the code of the component where i want to get the modal
<template>
<div id="contenedor">
<div id="padre">
<div id="barra">
<Modal/>
<div v-if="producto === 'bebidas'" class="tabcontent">
<div>
<button v-on:click="modal()" data-toggle="modal" data-target="#exampleModal">
<h6>Inka Kola</h6>
<img src="../../assets/incakolaPersonal.jpg" />
</button>
</div>
<div>
<button>
<h6>Coca Kola</h6>
<img src="../../assets/cocaKolaPersona.png" />
</button>
</div>
<div>
<button>
<h6>Sprite</h6>
<img src="../../assets/sprite.webp" />
</button>
</div>
<div>
<button>
<h6>Cielo</h6>
<img src="../../assets/cieloPersonal.webp" />
</button>
</div>
<div>
<button>
<h6>San Mateo</h6>
<img src="../../assets/sanmateoPersonal.webp" />
</button>
</div>
<div>
<button>
<h6>Ruskalla</h6>
<img src="../../assets/ruskalla.webp" />
</button>
</div>
<div>
<button>
<h6>Ron</h6>
<img src="../../assets/ron.webp" />
</button>
</div>
<div>
<button>
<h6>Cristal</h6>
<img src="../../assets/cristal.jpg" />
</button>
</div>
</div>
<div v-if="producto === 'carnes'" class="tabcontent">
<div>
<button>
<h6>Pollo</h6>
<img src="../../assets/pollo.jpg" />
</button>
</div>
<div>
<button>
<h6>Carne</h6>
<img src="../../assets/carne.jpg" />
</button>
</div>
<div>
<button>
<h6>Cerdo</h6>
<img src="../../assets/cerdo.jpg" />
</button>
</div>
</div>
<div v-if="producto === 'tuberculos'" class="tabcontent">
<div>
<button>
<h6>Papa</h6>
<img src="../../assets/papa.jpg" />
</button>
</div>
<div>
<button>
<h6>Yuca</h6>
<img src="../../assets/yuca.jpg" />
</button>
</div>
<div>
<button>
<h6>Olluco</h6>
<img src="../../assets/olluco.webp" />
</button>
</div>
<div>
<button>
<h6>Jengibre</h6>
<img src="../../assets/jengibre.jpg" />
</button>
</div>
</div>
</div>
</div>
</template>
<style lang="sass" scoped>
#contenedor
display: flex
justify-content: center
#padre
width: 100%
display: flex
flex-direction: column
justify-content: center
#barra
margin-top: 40px
display: flex
button
border-radius: 0px
.tabcontent
background-color: #999999
display: flex
flex-wrap: wrap
justify-content: space-around
width: 100%
height: 100%
div
margin: 20px
flex-grow: 1
button
border: 0px
img
width: 100px
height: 120px
</style>
<script>
import Modal from "./Modal";
export default {
name: "Barra",
data: function () {
return {
producto: "bebidas",
modalEstado : false
};
},
methods: {
mostrar: function (a) {
this.producto = a;
},
modal(){
this.modalEstado=true;
console.log(this.modalEstado);
}
},
};
</script>

Related

toggle accordion only with icon & add a click event on button

I want to toggle the accordion only with the icons to add a click event on the button. How do I do this? I have tried this--
<html>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
<div id="app">
<div id="t_accordion">
<div class="accordion" id="accordionExample">
<div class="accordion-item">
<h2 class="accordion-header " id="headingOne">
<button #click="toggleTheme" class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="false" aria-controls="collapseOne">
User
</button>
</h2>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingTwo">
<button #click="toggleTheme" class="accordion-button " type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="true" aria-controls="collapseTwo">
View
</button>
</h2>
</div>
<div>
<div id="collapseOne" class="accordion-collapse collapse " aria-labelledby="headingOne" data-bs-parent="#accordionExample">
<div class="accordion-body">
<strong>User Content</strong>
</div>
</div>
<div id="collapseTwo" class="accordion-collapse collapse show" aria-labelledby="headingTwo" data-bs-parent="#accordionExample">
<div class="accordion-body">
<strong>View Content</strong>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Don't forget to include Vue from CDN! -->
<script src="https://unpkg.com/vue#2"></script>
<script>
new Vue({
el: '#app', //Tells Vue to render in HTML element with id "app"
data() {
return {
message: 'Hello World!'
}
},
methods:{
toggleTheme(){
// alert('clicked')
this.isActive = !this.isActive;
}
}
});
</script>
<style>
.accordion-button {
pointer-events:none;
}
.accordion-button::after {
pointer-events: all;
}
</style>
</html>
In this snippet The toggle on icon is working but Click event on button does not work.
How do I do the accordion toggle on icon & click event on button separately?
I just split the button in two ways
<html>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
<div id="app">
<div id="t_accordion">
<div class="accordion" id="accordionExample">
<div class="accordion-item">
<h2 class="accordion-header " id="headingOne">
<button class="d-flex bg-white mx-auto">
<a #click="toggleTheme">User</a>
</button>
</h2>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingTwo">
<button class="d-flex bg-white mx-auto">
<a #click="toggleTheme">View</a>
</button>
</h2>
</div>
<div>
<div id="collapseOne" class="accordion-collapse collapse " aria-labelledby="headingOne" data-bs-parent="#accordionExample">
<div class="accordion-body">
<strong>User Content</strong>
</div>
</div>
<div id="collapseTwo" class="accordion-collapse collapse show" aria-labelledby="headingTwo" data-bs-parent="#accordionExample">
<div class="accordion-body">
<strong>View Content</strong>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Don't forget to include Vue from CDN! -->
<script src="https://unpkg.com/vue#2"></script>
<script>
new Vue({
el: '#app', //Tells Vue to render in HTML element with id "app"
data() {
return {
message: 'Hello World!'
}
},
methods:{
toggleTheme(){
// alert('clicked')
this.isActive = !this.isActive;
}
}
});
</script>
<style>
.accordion-button {
pointer-events:none;
}
.accordion-button::after {
pointer-events: all;
}
</style>
</html>

vue accordion prevents events from firing on click

I just started learning Vue2.
I use bootstrap accordion.
I want to be able to click the 'hello button' without triggering the 'collapse' event.
How to do this?
<template>
<div class="accordion" id="accordionExample">
<div class="accordion-item" v-for="i in 3" :key="i">
<h2 class="accordion-header" :id="`headingOne${i}`">
<button class="accordion-button"
type="button" data-bs-toggle="collapse"
:data-bs-target="`#collapseOne${1}`"
aria-expanded="true"
:aria-controls="`collapseOne${1}`"
>
Accordion Item #{{ i }}
<button class="btn-primary" #click=test>hello button</button>
</button>
</h2>
<div :id="`collapseOne${i}`" class="accordion-collapse show"
:aria-labelledby="`headingOne${i}`">
<div class="accordion-body">
<strong>This is the first item's accordion body.</strong>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Learn',
methods: {
test () {
console.log('hello')
}
}
}
</script>
You have to make sure that your hello-button is not nested inside the accordion-button. Just put both buttons right next to eachother. You might have to adjust the css to position them properly.
<template>
<div class="accordion" id="accordionExample">
<div class="accordion-item" v-for="i in 3" :key="i">
<h2 class="accordion-header" :id="`headingOne${i}`">
<button class="accordion-button"
type="button" data-bs-toggle="collapse"
:data-bs-target="`#collapseOne${1}`"
aria-expanded="true"
:aria-controls="`collapseOne${1}`"
>
Accordion Item #{{ i }}
</button>
<button class="btn-primary" #click=test>hello button</button>
</h2>
<div :id="`collapseOne${i}`" class="accordion-collapse show"
:aria-labelledby="`headingOne${i}`">
<div class="accordion-body">
<strong>This is the first item's accordion body.</strong>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Learn',
methods: {
test () {
console.log('hello')
}
}
}
</script>

VueJS reusable component not updated data for second component

I am trying to create one component in VueJS and need to reuse that component.
below is code for me.
Vue.component("radio" , {
props: ['selectGender'],
data: function() {
return{
selected: 1
}
},
template : `
<div class="modal fade" :id="compId" style="background: rgb(0, 0, 0, 0.8);">
<div class="modal-dialog default-font" style="top: 30%;">
<div class="modal-content center">
<div class="modal-header base-bg center">
<div class="center">
<span class="validationHeadSpan">Select Gender</span><br/>
</div>
<button type="button" class="close modal-close" data-dismiss="modal" style="font-size:3rem">×</button>
</div>
<div class="modal-body t-left" id="printArea">
<div class="container">
<div class="row" style="padding: 0rem 1rem;">
<div class="col">
<div class="custom-control custom-radio" style="margin: 1rem 0rem;">
<input class="custom-control-input" type="radio" id="rdbMale" value="0" checked v-model="selected"/>
<label class="custom-control-label" for="rdbMale">
<div class="addr_header_1" style="margin-top: 0.8rem;">Male</div>
</label>
</div>
</div>
<div class="col">
<div class="custom-control custom-radio" style="margin: 1rem 0rem;">
<input class="custom-control-input" type="radio" id="rdbFemale" value="0" checked v-model="selected"/>
<label class="custom-control-label" for="rdbFemale">
<div class="addr_header_1" style="margin-top: 0.8rem;">Female</div>
</label>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer center">
<button type="button" class="button" data-dismiss="modal" v-on:click="selectGender(selected)"><span class="validationButtonContent">Select</span></button>
</div>
</div>
</div>
</div>
`,
mounted : function(){
},
methods : {
}
});
Here is my another component from where i am opening reusable component.
Vue.component("Component1" , {
data: function() {
return{
selected: 1
}
},
template : `
<div>
<radio ref="returnOpenFirst" :selectGender="selectGenderFirst"></radio>
<radio ref="returnOpenSecond" :selectGender="selectGenderSecond"></radio>
</div>
<div class="btn btn-primary formButton" v-on:click="openFirst">
<span>Open First</span>
</div>
<div class="btn btn-primary formButton" v-on:click="openSecond">
<span>Open First</span>
</div>
`,
mounted : function(){
},
methods : {
openFirst:function(){
jQuery(self.$refs.returnOpenFirst.$el).modal({
'backdrop' : false
}).modal('show');
},
openSecond:function(){
jQuery(self.$refs.returnOpenSecond.$el).modal({
'backdrop' : false
}).modal('show');
},
selectGenderFirst:function(gender){
console.log("First Gender", gender);
},
selectGenderSecond:function(gender){
console.log("Second Gender", gender);
},
}
});
While opening second component, data property is updated of first component only not for second component.
Any help is highly appreciated.
Thanks in advance.
Here i found solution.
Vue.component("radio" , {
props: ['selectGender','type'],
data: function() {
return{
selected: 1
}
},
template : `
<div class="modal fade" :id="compId" style="background: rgb(0, 0, 0, 0.8);">
<div class="modal-dialog default-font" style="top: 30%;">
<div class="modal-content center">
<div class="modal-header base-bg center">
<div class="center">
<span class="validationHeadSpan">Select Gender</span><br/>
</div>
<button type="button" class="close modal-close" data-dismiss="modal" style="font-size:3rem">×</button>
</div>
<div class="modal-body t-left" id="printArea">
<div class="container">
<div class="row" style="padding: 0rem 1rem;">
<div class="col">
<div class="custom-control custom-radio" style="margin: 1rem 0rem;">
<input class="custom-control-input" type="radio" :id="'rdbMale'+type" value="0" checked v-model="selected"/>
<label class="custom-control-label" :for="'rdbMale'+type">
<div class="addr_header_1" style="margin-top: 0.8rem;">Male</div>
</label>
</div>
</div>
<div class="col">
<div class="custom-control custom-radio" style="margin: 1rem 0rem;">
<input class="custom-control-input" type="radio" :id="'rdbFemale'+type" value="0" checked v-model="selected"/>
<label class="custom-control-label" :for="'rdbFemale'+type">
<div class="addr_header_1" style="margin-top: 0.8rem;">Female</div>
</label>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer center">
<button type="button" class="button" data-dismiss="modal" v-on:click="selectGender(selected)"><span class="validationButtonContent">Select</span></button>
</div>
</div>
</div>
</div>
`,
mounted : function(){
},
methods : {
}
});
Issue with same id created by VueJs, we need to pass one dynamic property and with the use of that we need to create id for radio.
Thank you guys.

Add scrollbar to bootstrap modal body

I'm trying to add scrollbar to bootstrap modal body. But it add to entire content.How to add it to only to body.was using modals which had long content, and the modals automatically scrolled when a given max height was reached.
This is my code
<head>
<!-- Bootstrap CSS-->
<link href="/<s:text name="app.name"/>/css/bootstrap.min.css" rel="stylesheet" type="text/css">
.modal-body {
max-height: calc(100vh - 212px);
overflow-y: auto;
}
</head>
<body>
<div>
<s:if test="user.level == 0 && name != ''">
<button id="roleBtn" class="btn btn-info" type="button" onclick=""
data-toggle="modal" data-target="#roleModal">
<s:text name="roles"/>
</button>
</s:if>
</div>
<div class="modal" id="roleModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog" style="overflow-y: scroll; max-height:80%; margin-top: 60px; margin-bottom:30px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel"><s:text name="headingRoles"/></h4>
</div>
<s:form theme="simple" method="post" action="UserSupport">
<div class="modal-body">
<div class="container-fluid">
<s:hidden name="docType" value="userLevel"/>
<div>
<s:hidden name="name"/>
<s:iterator value="userRoles" status="rowstatus">
<s:hidden name="userRoles[%{#rowstatus.index}].role" value="%{role}"/>
<div class="form-group col-xs-12">
<div class="col-xs-4"></div>
<div class="col-xs-8" align="left">
<div class="checkbox">
<label></label><s:checkbox name="userRoles[%{#rowstatus.index}].selected"
value="name != ''"/> <s:property
value="roleName"/></label>
</div>
</div>
</div>
</s:iterator>
</div>
</div>
</div>
<div class="modal-footer">
<div class="panel-body" align="center">
<s:submit method="saveRoles" cssClass="btn btn-primary"
value="%{getText('save')}"></s:submit>
<button type="button" method="resetRoles" class="btn btn-default" data-dismiss="modal">
<s:text name="close"/>
</button>
</div>
</div>
</s:form>
</div>
</div>
</div>
</body>
it doesn't work as expected. The modal window does reach a maximum size, but it just cuts its content there and the footer is not even displayed.Answers are welcome
Thank you
Just provide overflow hidden to the .modal class and provide overflow scroll to the modal body...
.modal .modal-content{
overflow:hidden;
}
.modal-body{
overflow-y:scroll; // to get scrollbar only for y axis
}
Hope it will help you :)
<head>
<!-- Bootstrap CSS-->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style>
body,html{
width:100%;
height:100%;
padding:0px;
margin:0px;
}
.modal-dialog{
height:calc(100% - 60px);
}
.modal-content{
height:100%;
}
.modal-header{
height:50px;
}
.model-footer{
height:75px;
}
.modal-body {
height:calc(100% - 125px);
overflow-y: scroll; /*give auto it will take based in content */
}
</style>
</head>
<body>
<div>
<s:if test="user.level == 0 && name != ''">
<button id="roleBtn" class="btn btn-info" type="button" onclick=""
data-toggle="modal" data-target="#roleModal">Open model
<s:text name="roles"/>
</button>
</s:if>
</div>
<div class="modal" id="roleModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog" style="">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel"><s:text name="headingRoles"/></h4>
</div>
<s:form theme="simple" method="post" action="UserSupport">
<div class="modal-body">
<div class="container-fluid">
<s:hidden name="docType" value="userLevel"/>
<div>
<s:hidden name="name"/>
<s:iterator value="userRoles" status="rowstatus">
<s:hidden name="userRoles[%{#rowstatus.index}].role" value="%{role}"/>
<div class="form-group col-xs-12">
<div class="col-xs-4"></div>
<div class="col-xs-8" align="left">
<div class="checkbox">
<label></label><s:checkbox name="userRoles[%{#rowstatus.index}].selected"
value="name != ''"/> <s:property
value="roleName"/></label>
</div>
</div>
</div>
</s:iterator>
</div>
</div>
</div>
<div class="modal-footer">
<div class="panel-body" align="center">
<s:submit method="saveRoles" cssClass="btn btn-primary"
value="%{getText('save')}"></s:submit>
<button type="button" method="resetRoles" class="btn btn-default" data-dismiss="modal">
<s:text name="close"/>
</button>
</div>
</div>
</s:form>
</div>
</div>
</div>
</body>
https://getbootstrap.com/docs/4.5/components/modal/#exampleModalLongTitle
<!-- Scrollable modal -->
<div class="modal-dialog modal-dialog-scrollable">
...
</div>
If you use Bootstrap, dont add some CSS, just use class "overflow-hidden" on the div with modal-content class.

Nested transition modal

i'm creating modal with vuejs and following this example but i create a separated file for modal so i can simply call my modal component anywhere i need to like this
here is my modal.vue
<template>
<div class="modal-mask" #click="close">
<div class="modal-dialog" :class="size">
<div class="modal-content">
<div class="modal-header" :class="color">
<button type="button" class="close" #click="close">×</button>
<h6 class="modal-title">{{ title }}</h6>
</div>
<div class="modal-body">
<slot></slot>
</div>
<div class="modal-footer">
<slot name="button"></slot>
</div>
</div>
</div>
</div>
</template>
<script>
export default{
props: ['title','color','size'],
methods: {
close(){
this.$emit('close');
}
}
}
</script>
<style>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
transition: opacity .3s ease;
}
</style>
and in index.vue where i want to call it i just simply
<app-modal
:title="modalTitle"
:size="modalSize"
:color="modalColor"
v-if="modalShow"
#close="modalShow = false"
>
</app-modal>
now my question is i want to use 2 kind of transition, first is in my index.vue page
<transition name="modal">
<app-modal
:title="modalTitle"
:size="modalSize"
:color="modalColor"
v-if="modalShow"
#close="modalShow = false"
>
</app-modal>
</transition>
and the second one is in my modal.vue like this
<template>
<div class="modal-mask" #click="close">
<transition name="modal-inside">
<div class="modal-dialog" :class="size">
<div class="modal-content">
<div class="modal-header" :class="color">
<button type="button" class="close" #click="close">×</button>
<h6 class="modal-title">{{ title }}</h6>
</div>
<div class="modal-body">
<slot></slot>
</div>
<div class="modal-footer">
<slot name="button"></slot>
</div>
</div>
</div>
</transition>
</div>
</template>
why i want it like that well simply because in there is modal-mask class that warp entire modal and that css class is add some dark/shade background so user can focus on the modal.... exactly like bootstrap modal fade effect and then after that i want everything inside div modal-dialog to show/transition after modal-mask is already finished its transition
so it will just first darken background and then show modal... they move separately one after another.. not at the same time
or to be more easy to imagine it i want to generate exactly like bootstrap modal