vue accordion prevents events from firing on click - vuejs2

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>

Related

Why doesn't my modal component get the right value of props?

The parent component has pass an integer to the child component - <DeleteModal>.
<DeleteModal> includes a button and a Modal. With clicking on the button the modal will be displayed asking for the confirmation. I've tested that the props is correctly passed to <DeleteModal> by print out the eventIndex when clicking on the button. However, when showing the eventIndex in the Modal it's always the smallest index (e.g. 0).
<template>
<button
type="button"
class="btn btn-close"
data-bs-toggle="modal"
data-bs-target="#removeModal"
aria-label="Remove"
#click="test"
></button>
<div class="modal fade" id="removeModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Remove Event</h5>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div class="modal-body">
Are you sure that you want to remove this event from this csv file?
This process cannot be resumed.
eventIndex: {{ this.eventIndex }}
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal"
#click="test"
>
Cancel
</button>
<button
type="button"
class="btn btn-primary"
data-bs-dismiss="modal"
#click="remove_event"
>
Remove
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
props: ["eventIndex"],
methods: {
test() {
console.log(this.eventIndex);
},
remove_event() {
//...
},
},
};
</script>
<style lang=""></style>

Vue v-for is displaying more than one image on click

I am using vue to show a photo that is being pulled from a mysql DB.
I loop through the images but when I click to show, all the images show instead of just the one that I want to show (the single image button I clicked). How do I get only one image to show up at a time?
UPDATED
<div>
<div v-for="(image, index) in images" :key="index">
<div class="dropdown">
<div>
<a class="dropdown-item preview-link" #click="togglePreview(index)">
Preview
</a>
</div>
</div>
<div v-if="currentIndex === index" class="modal-dialog modal-dialog-centered modal-md" role="image" style="max-width: 700px;">
<div class="modal-content" style="overflow: hidden;">
<div class="modal-header">
<h5 class="modal-title">{{image.title}}</h5>
<button type="button" class="close modal-close-button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<img :src="'/storage/images/' + image.name + '.jpg'">
</div>
</div>
</div>
</div>
</div>
In my vue methods:
togglePreview(index) {
this.currentIndex = this.currentIndex === index?-1:index
},
Vue Data
data() {
return {
currentIndex: -1,
}
},

(Vue.js) modal close event

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>

Vue: method is not a function within inline-template component tag

I have this component:
<template>
<div class="modal fade modal-primary" id="imageModal" tabindex="-1" role="dialog" aria-labelledby="ImageLabel"
aria-hidden="true">
<div class="modal-dialog modal-lg animated zoomIn animated-3x">
<div class="modal-content">
<ais-index index-name="templates"
app-id="BZF8JU37VR"
api-key="33936dae4a732cde18cc6d77ba396b27">
<div class="modal-header">
<algolia-menu :attribute="category"
:class-names="{ 'nav-item__item': 'nav-color', 'nav-item__link': 'nav-link', 'nav-item__item--active': 'active'}">
</algolia-menu>
</div>
<div class="modal-body">
<div class="container">
<ais-results :results-per-page="10" inline-template>
<div class="row">
<div class="col-6" v-for="result in results.slice(0, 5)" :key="result.objectID">
<div class="card" #click="getTemplate(result)">
<img class="img-fluid" v-lazy="result.image"/>
<div class="card-body">
<p>{{ result.description }}</p>
</div>
<div class="card-footer">
<small>Created: {{ result.created_at }}</small>
</div>
</div>
</div>
<div class="col-6" v-for="result in results.slice(5, 10)" :key="result.objectID">
<div class="card">
<img class="img-fluid" v-lazy="result.image"/>
<div class="card-body">
<p>{{ result.description }}</p>
</div>
<div class="card-footer">
<small>Created: {{ result.created_at }}</small>
</div>
</div>
</div>
</div>
</ais-results>
</div>
</div>
</ais-index>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</template>
<script>
import Algolia from '#/components/algolia/menu';
export default {
components: {
"algolia-menu": Algolia,
},
data() {
return {
category: 'category',
};
},
methods: {
getTemplate(result) {
console.log(result)
}
}
}
</script>
I have a click listener on the .card div within my <ais-results> tag which calls my getTemplate method. But, whenever I click on that element, it produces this error:
imageModal.vue?8d74:85 Uncaught TypeError: _vm.getTemplate is not a
function
at click (imageModal.vue?8d74:85)
at invoker (vue.runtime.esm.js:2023)
at HTMLDivElement.fn._withTask.fn._withTask
Why is this happening? I have tried #click.native as well, but that didn't work.
The issue is that you’re using an inline template for your <ais-results> component tag, so the data references within that tag are scoped to the <ais-results> instance. This means Vue is looking for a getTemplate method on the <ais-results> component, but not finding it.
In your case, instead of directly calling getTemplate, you could emit an event with the result data and then listen for the event on the <ais-results> tag.
Below is a simplified example where clicking on the .card div in the inline template will emit a card-click event (#click="$emit('card-click', result)"). The <ais-results> tag has a listener for that event (#card-click="getTemplate"), so when the card-click event is fired, the getTemplate method will be called with the result data being passed automatically.
<ais-results :results-per-page="10" inline-template #card-click="getTemplate">
<div class="row">
<div class="col-6" v-for="result in results.slice(0, 5)" :key="result.objectID">
<div class="card" #click="$emit('card-click', result)">
...
</div>
</div>
</div>
</ais-results>

Hide html elements in vuejs2

I want to hide html elements during the initial load, by clicking a button or link i will show those html elements. I can't find a solution to hide or show the element in vuejs2 version. I can able to see few options in vuejs but i am not sure how to use those methods. Below is my component code in that i want to hide the html element(id) "Message".
<template>
<div class="row">
<div class="col-lg-12">
<label class="checkbox checkbox-inline no_indent">
<input type="checkbox" value="">Show stats
</label>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="panel-group">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">List Values</h3>
</div>
<div class="panel-body">
<button type="button" id="btn1" class="btn btn-warning btn-md" v-on:click="showWorkflow">Test 1</button>
<button type="button" id="btn2" class="btn btn-danger btn-md" v-on:click="showWorkflow">Test 2</button>
<button type="button" id="btn3" class="btn btn-info btn-md" v-on:click="showWorkflow">Test 3</button>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div id="Message">Hello i am here</div>
</div>
</template>
<script>
export default {
name: 'jobs',
methods: {
showWorkflow: function (e) {
console.log(e.target.id)
}
}
}
</script>
In Vue, you use the v-if directive to conditionally render elements.
You could also use the v-show directive if you wanted to just toggle the CSS display property.
See the section in the docs on Conditional Rendering for more info.
In your specific case, make showWorkflow a data property initially set to false.
Use this as the argument for a v-if directive on the content that you want to initially hide.
Then, when you want to show the content, set showWorkflow to true:
new Vue({
el: '#app',
data() {
return {
showWorkflow: false,
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
<div v-if="showWorkflow">
Here is the workflow
</div>
<button #click="showWorkflow = true">Show Workflow</button>
</div>
Here is the documentation on conditional rendering in Vue