Use multiple modals in template vue.js - javascript

I'm trying to create one modal for each row but when i open one modal all the other modals open as well. i suppose this have something to do with the id but i don't know how to fix it.
Using vue#2.6.12
<template #cell(add)="row">
<div>
<b-button
v-b-modal="'row'"
class="bg-dark text-white"
test-id="showOrHideAddButton"
size="sm"
>
add
</b-button>
<b-modal id=row>
Hello From My Modal!
</b-modal>
</div>
</template>

As user3113901 wrote in the comments above ID's should be always unique. Only class could/should be used multiple times.
Here you can see an example how it should work:
<template>
<div>
<b-button
v-b-modal="'row1'" <!-- use unique ID here --->
class="bg-dark text-white"
test-id="showOrHideAddButton"
size="sm"
> add </b-button>
<b-modal id="row1"> <!-- Here you have to put your id-name into "" --->
Hello From My First Modal!
</b-modal>
<b-button
v-b-modal="'row2'" <!-- use unique ID here --->
class="bg-dark text-white"
test-id="showOrHideAddButton"
size="sm"
> add </b-button>
<b-modal id="row2"> <!-- Here you have to put your id-name into "" --->
Hello From My Second Modal!
</b-modal>
</div>
</template>
If you set v-b-modal equal to your id in your <b-modal> and make it all unique it should work out!

Related

Trigger a button inside a link with Vue

I have a set of images with some information like the author and now I'm adding a few buttons to allow users to like images.
Since the image has a link to the images screen I don't know how to trigger the button avoiding to fire the link.
Here is the code, I'm using Vuetify and Nuxt:
<nuxt-link
:to="
`/photo/${slotProps.item.id}/${
slotProps.item.slug
}`
"
>
<v-hover>
<v-img
slot-scope="{ hover }"
:src="slotProps.item.url"
>
<v-fade-transition mode="in-out">
<div
v-if="hover"
class="d-flex transition-fast-in-fast-out photo-overlay pa-2"
>
<div
class="d-flex pl-1 credits justify-space-between align-center w-100"
>
<div>
<nuxt-link
:to="
`/user/${slotProps.item.pId}`
"
class="secondary--text body-2 d-inline-block"
>
<v-avatar size="30">
<img
:src="slotProps.item.avatar"
:alt="`${slotProps.item.name}`"
/>
</v-avatar>
<span class="ml-2">
{{ slotProps.item.name }}
</span>
</nuxt-link>
</div>
<div>
<v-menu
v-model="addToGalleriesMenu"
:close-on-content-click="false"
:nudge-width="200"
>
<template v-slot:activator="{ on, attrs }">
<v-btn v-on="on" v-bind="attrs" icon color="secondary">
<v-icon small>
fal fa-hearth
</v-icon>
</v-btn>
</template>
<v-card outlined>
<v-card-title>Test</v-card-title>
</v-card>
</v-menu>
</div>
</div>
</div>
</v-fade-transition>
</v-img>
</v-hover>
</nuxt-link>
The code above generate an image, on mouse hover a layer appear at the bottom showing the name and a button to like the image.
Clicking on the user link it works fine, as expected. Clicking on the button that should fire an action is not working because the image link get clicked.
How can I work around it?
You can stop event propagation to the parent element very easily using Vue click modifiers:
<a href="example.com">
...
<v-btn #click.stop.prevent="test()">
...
You can achieve the same thing without using Vue modifiers:
<a href="example.com">
...
<v-btn #click="test($event)">
...
methods: {
test (event) {
event.preventDefault()
event.stopPropagation()
}
}

Is there a way that v-on:click displays modal for particular objects only?

When I use the code below, it displays three buttons for SAN, DAVID, and JAY. If I click on SAN or David or Jay it generates the modal three times. Is there a way that when I click on button SAN, it displays modal only one time with the customerName (SAN) inside the modal?
My template file
<div id="app">
<div v-for="post in posts" v-bind:key="post.createdAt">
<div>
<b-col md="3">
<div v-for="item in post.items" v-bind:key="item.id">
<div v-on:click="item.id = !item.id" style="color: blue;">
<b-button v-b-modal.modal-xl variant="info">{{post.customerName}}</b-button>
/** the code display the modal from BOOTSTRAP VUE **/
<b-modal id="modal-xl" centered size="xl" title="TEAM NAME 1">
<p> Booker Name = <u style="font-weight:bold;">{{post.customerName}}</u> </p>
<b-container class="bv-example-row">
<b-row style="font-weight:bold;">
<b-col><p>Child Name</p></b-col>
<b-col><p>Text Number</p></b-col>
<b-col><p>No Show</p></b-col>
</b-row>
<b-row>
<b-col><p>David</p></b-col>
<b-col><p>P</p></b-col>
<b-col><p>817 360 2705</p></b-col>
<b-col><input type="checkbox" v-model="subchildNoShow"/></b-col>
</b-row>
</b-container>
</b-modal>
/** END OF MODAL **/
</div>
</div>
</b-col>
</div>
</div>
</div>
Script Function
export default {
name: 'App',
components: {
},
data(){
return{
searchQuery: '',
posts: [],
subchildNoShow: []
}
}
}
JSON File values
data{
Object[0]{
customerName:'San',
createdAt: '2020-04-15',
items:{
id:'1',
arrivalTime:'06:00 PM'
}
}
Object[1]{
customerName:'David',
createdAt: '2020-04-15',
items:{
id:'2',
arrivalTime:'07:00 PM'
}
}
Object[2]{
customerName:'Jay',
createdAt: '2020-04-15',
items:{
id:'3',
arrivalTime:'07:00 PM'
}
}
}
You should only create on modal. Move it outside of the v-for
/** the code display the modal from BOOTSTRAP VUE **/
<b-modal id="modal-xl" centered size="xl" title="TEAM NAME 1">
<p> Booker Name = <u style="font-weight:bold;">{{selectedCustomerName}}</u> </p>
<b-container class="bv-example-row">
<b-row style="font-weight:bold;">
<b-col><p>Child Name</p></b-col>
<b-col><p>Text Number</p></b-col>
<b-col><p>No Show</p></b-col>
</b-row>
<b-row>
<b-col><p>David</p></b-col>
<b-col><p>P</p></b-col>
<b-col><p>817 360 2705</p></b-col>
<b-col><input type="checkbox" v-model="subchildNoShow"/></b-col>
</b-row>
</b-container>
</b-modal>
/** END OF MODAL **/
and set selectedPost on click and show the modal.
<div v-on:click="selectItem(post, item)"
and declare the selectItem method
methods: {
selectItem (post, item) {
item.id = !item.id
this.selectedCustomerName = post.customerName
// show the modal
$bvModal.show('modal-xl')
}
}
Try to make the modal component unique for each item as follows :
<b-button #click="$bvModal.show('modal'+item.id)" variant="info">{{post.customerName}}</b-button>
<!-- v----------------------^ -->
<b-modal :id="'modal'+item.id" centered size="xl" title="TEAM NAME 1">
based on the modal instance show method you concatenate the item id to the modal word which gives you for example modal1 that is the method parameter, then provide this as an id to the modal via :id="'modal'+item.id"

Vuejs & Vuetify : Is there a way to loop around template with datatable from vuetify (with v-slot dynamic)?

I have several datatable with server-side pagination, search fields and filterable fields
However, I would like to be able to generate a component and use the props to avoid modifying the same thing three times
Is there a way to loop around template with datatable from vuetify (with v-slot dynamic) ?
for example :
<template v-slot:header.id="{ header }">
<div class="pointer border-right pa-2">
<span class="title" #click.prevent="sortBy('id')">
ID
<v-icon class="ml-2">{{icon.id}}</v-icon>
</span>
<v-text-field v-model="searcher.ticket_id.value" type="text"
label="Rechercher..."></v-text-field>
</div>
</template>
<template v-slot:header.name="{ header }">
<div class="pointer border-right pa-2">
<span class="title" #click.prevent="sortBy('name')">
Nom du ticket
<v-icon class="ml-2">{{icon.name}}</v-icon>
</span>
<v-text-field v-model="searcher.ticket_name.value" type="text"
label="Rechercher..."></v-text-field>
</div>
</template>
Become (not functional) :
<template v-for="(item, i) in headers" v-slot:item.text="{ header }">
<div class="pointer border-right pa-2">
<span class="title" #click.prevent="sortBy(item.name)">
{{item.name}}
<v-icon class="ml-2">{{icon[item.name]}}</v-icon>
</span>
<v-text-field v-model="item.searcher" type="text"
label="Rechercher..."></v-text-field>
</div>
</template>
If i add the key , i have '<template>' cannot be keyed. Place the key on real elements instead
and if i remove this i have Elements in iteration expect to have 'v-bind:key' directives
However I came across several sources that demonstrate the opposite
https://v2.vuejs.org/v2/guide/list.html#v-for-on-a-lt-template-gt
Fix: require-v-for-key shouldn't be raised on slots
vue-language-server : Elements in iteration expect to have 'v-bind:key' directives
Thank you
Edit 20/12 :
https://github.com/vuejs/eslint-plugin-vue/issues/1006
How can I make the v-slot attribute dynamically with the vuetify data table ?
Here is my code :
<template v-for="(head, i) in headers" v-slot:header[header.value]="{header}">
<div :key="i" class="pointer border-right pa-2">
<span class="title" #click.prevent="sortBy('id')">
{{head}} <br> {{header}}
<v-icon class="ml-2">{{icon.id}}</v-icon>
</span>
<v-text-field v-model="searcher.ticket_id.value" type="text"
label="Rechercher..."></v-text-field>
</div>
</template>
It cannot be mounted on the table column
I need to use v-slot:header.id="{header}" for the mounted on the id column but I have to make id dynamic according to my loop
how to do ?
Thank you
I find it
I added head: 'header.id' in my list so i can use <template v-for="(head, i) in headers" v-slot:[headers[i].head]="{header}">
I had to do
<template v-for="(col, i) in filters" v-slot:[`header.${i}`]="{ header }">
in my case
filters: { 'name': [], 'calories': [] },

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.

neon-animated-pages with embedded dom-repeat element

We are building a survey mechanism where we can have the user create their own set of questions, the type, etc. The users can show up a single element at a time. Or a group of questions. I use the neon-animated-pages to go from one singular question to another.
-- index.html --
<iron-pages attr-for-selected="data-route" selected="{{route}}">
<section data-route="home">
<test-survey surveyid="99999999-9999-9999-9999-999999999999" submissionid='00000000-0000-0000-0000-000000000000'}' ></test-survey>
</section>
<section data-route="users">
<paper-material elevation="1">
</paper-material>
</section>
<section data-route="user-info">
<paper-material elevation="1">
</paper-material>
</section>
<section data-route="contact">
<paper-material elevation="1">
</paper-material>
</section>
</iron-pages>
--test-survey.html--
<div class="vertical layout">
<div class="flex">
<neon-animated-pages id="views" class="flex" selected="0" entry-animation="slide-from-right-animation" exit-animation="slide-left-animation">
<test-template items="{{survey.Questions}}" id="surveyquestions">
</test-template>
</neon-animated-pages>
<paper-toast
id="toast"
text="Saved successfully.">
</paper-toast>
</div>
</div>
Since needing to be able to group questions together, we moved the following code to another file, stand alone so it can be called from a place where single questions are asked. Or from a place where it will take a list of questions as a group and show them within one section.
--test-template.html--
<template>
<template is="dom-repeat" id="surveyquestions" items="{{items}}" sort="_sort">
<template is="dom-if" if="{{isFormat(item.Type, 'Single-Select')}}" >
<question-singleselect question="{{item}}"></question-singleselect>
</template>
<template is="dom-if" if="{{isFormat(item.Type,'Open-Ended')}}">
<question-openended question="{{item}}"></question-openended>
</template>
<template is="dom-if" if="[[isFormat(item.Type,'Multi-Select')]]">
<question-multiselect question="{{item}}"></question-multiselect>
</template>
<template is="dom-if" if="[[isFormat(item.Type,'Section')]]">
<question-section question="{{item}}"></question-section>
</template>
<template is="dom-if" if="{{isFormat(item.Type,'Numerical')}}">
<question-numerical question="{{item}}"></question-numerical>
</template>
</template>
</template>
--test-chrome.html--
<template>
<paper-card heading="{{question.Title}}" id="paper-card-{{question.Id}}">
<div class="card-content {{question.Type}}">
<div class="questionanswers">
<content select=".questionanswers"></content>
</div>
</div>
<div class="card-actions">
<paper-button class="raised primary" on-tap="prevAction" id="prevButton_{{question.Id}}" hidden$="{{_hidePrev(question.Type)}}">Previous</paper-button>
<paper-button class="raised primary" on-tap="nextAction" id="nextButton_{{question.Id}}" hidden$="{{_hideNext(question.Type)}}">Next</paper-button>
<paper-button class="raised primary" on-tap="saveAction" id="saveButton_{{question.Id}}" hidden$="{{_hideSave(question.Type)}}">Submit</paper-button>
</div>
</paper-card>
</template>
Once I put the list of question-types into a separate form, it stopped working. It listed all the questions on one page, instead of navigating from one question to the next. It works if the section of test-template.html is back in the test-survey.html

Categories

Resources