VueJS 3 - How to use draggable nested element but prevent duplicate item - vue.js

I am trying to create a simple survey builder with Vue3 and Vue Draggable. All is going well until I try to create a multiple choice question. This type of questions has its own sortable list of possible answers. When I add another multiple choice question it then pulls from the same list which makes sense but I have tried to use a v-if to check the parents ID to match the choice ID..
Basically if I add a new choice it adds to the all multiple choice questions, which makes sense, but how to I keep it to the current item I am in?
Any ideas? I know the code is mess, it will be refactored once it works.
<template>
<div class="p-4">
<div class="container mx-auto rounded-md grid grid-cols-12 gap-4 h-full">
<div class="col-span-4 p-3 flex flex-col min-h-screen bg-gray-200 shadow-md rounded-md">
<div class="text-lg font-bold w-full bg-blue-600 text-white rounded-md p-2 mb-4">Builder your survey</div>
<div class="sticky top-4">
<div class="text-lg font-bold">Components</div>
<draggable
class="p-2 rounded-md"
:list="componentsList"
:group="{ name: 'questions', pull: 'clone', put: false, sort: false }"
:clone="cloneItem"
sort: false
#change="log"
item-key="id"
>
<template #item="{ element }">
<div
class="bg-gray-300 p-4 rounded-md mt-2 shadow-sm hover:shadow-md cursor-pointer border border-blue-800 border-dashed"
>
{{ element.name }}
</div>
</template>
</draggable>
</div>
</div>
<div class="col-span-8 flex p-3 flex-col bg-white shadow-md rounded-md">
<div class="text-lg font-bold pt-4">Survey</div>
<draggable
class="w-full h-full border border-blue-400 rounded-md p-2 flex flex-col flex-1"
:list="questionsList"
group="questions"
#change="log"
handle=".handle"
itemKey="name + index"
>
<template #item="{ element, index }">
<div>
<div v-if="element.name == 'Single Line of Text'" class="bg-gray-300 p-2 rounded-md mt-2 mb-2 shadow-lg hover:shadow-md">
<div class="w-full text-sm text-left">{{ element.name }} {{element.id}}</div>
<div class="flex justify-between items-center p-2 bg-gray-200 rounded-md mb-4">
<div class="w-10 font-bold hidden">Q{{ index + 1 }}</div>
<div class="w-full pr-4">
<input
type="text"
class="w-full p-2 bg-transparent flex-grow"
placeholder="Question title here..."
v-model="element.text"
/>
</div>
<div class="flex ">
<div class="cursor-pointer">
<i class="handle las la-arrows-alt la-2x mr-2"></i>
</div>
<div #click="remove(index)">
<i class="las la-trash-alt text-red-800 la-2x cursor-pointer"></i>
</div>
</div>
</div>
<div>
<input
type="text"
class="w-full p-2 rounded-md border border-gray-400"
placeholder="User response will go here"
/>
</div>
<div class="text-left flex justify-between items-center p-2 bg-gray-200 rounded-md mt-2">
<div class="flex items-center">
<div><input type="checkbox" class="mr-2" /></div>
<div>Required?</div>
</div>
</div>
</div>
<!-- START problem area -->
<div v-else-if="element.name == 'Multiple Choice'" class="bg-gray-300 p-2 rounded-md mt-2 mb-2 shadow-lg hover:shadow-md">
<div class="w-full text-sm text-left">{{ element.name }} {{element.id}}</div>
<div class="flex justify-between items-center p-2 bg-gray-200 rounded-md mb-4">
<div class="w-10 font-bold hidden">Q{{ index + 1 }}</div>
<div class="w-full pr-4">
<input
type="text"
class="w-full p-2 bg-transparent flex-grow"
placeholder="Question title here..."
v-model="element.text"
/>
</div>
<div class="flex ">
<div class="cursor-pointer">
<i class="handle las la-arrows-alt la-2x mr-2"></i>
</div>
<div #click="remove(index)">
<i class="las la-trash-alt text-red-800 la-2x cursor-pointer"></i>
</div>
</div>
</div>
<div class="flex items-center ">
<draggable
class="p-2 rounded-md w-full"
:list="multipleChoiceList"
:group="{ name: 'choice', pull: false, put: false, sort: true }"
sort: true
handle=".handle"
#change="log"
item-key="question"
>
<template #item="{ element }">
<div
class="bg-blue-100 p-4 flex items-center justify-start rounded-md mt-2 shadow-sm hover:shadow-md cursor-pointer w-full"
>
<div class="flex items-center flex-grow"
>
<input type="checkbox" class="w-6 h-6">
<input
type="text"
class="p-2 bg-transparent flex-grow"
placeholder="Add choice here"
v-model="element.text"
/>
</div>
<div class="flex ">
<div class="cursor-pointer">
<i class="handle las la-arrows-alt la-1x mr-2"></i>
</div>
<div #click="remove(index)">
<i class="las la-trash-alt text-red-800 la-1x cursor-pointer"></i>
</div>
</div>
</div>
</template>
<template #footer>
<div>
<button class="p-2 bg-blue-300 mt-2 rounded-md" #click="addChoice(element.id)">Add</button>
</div>
</template>
</draggable>
</div>
<div class="text-left flex justify-between items-center p-2 bg-gray-200 rounded-md mt-2">
<div class="flex items-center">
<div><input type="checkbox" class="mr-2" /></div>
<div>Required?</div>
</div>
</div>
</div>
<!-- END problem area -->
<div v-else-if="element.name == 'Open Ended'" class="bg-gray-300 p-2 rounded-md mt-2 mb-2 shadow-lg hover:shadow-md">
<div class="w-full text-sm text-left">{{ element.name }} {{element.id}}</div>
<div class="flex justify-between items-center p-2 bg-gray-200 rounded-md mb-4">
<div class="w-10 font-bold hidden">Q{{ index + 1 }}</div>
<div class="w-full pr-4">
<input
type="text"
class="w-full p-2 bg-transparent flex-grow"
placeholder="Question title here..."
v-model="element.text"
/>
</div>
<div class="flex ">
<div class="cursor-pointer">
<i class="handle las la-arrows-alt la-2x mr-2"></i>
</div>
<div #click="remove(index)">
<i class="las la-trash-alt text-red-800 la-2x cursor-pointer"></i>
</div>
</div>
</div>
<div>
<textarea
class="h-32 w-full w-full p-2 rounded-md border border-gray-400"
></textarea>
</div>
<div class="flex items-center">
<div>Max Length</div>
<div>
<input
type="number"
class="mr-2 w-20 border border-gray-400 p-2 rounded-md ml-2"
/>
</div>
</div>
<div class="text-left flex justify-between items-center p-2 bg-gray-200 rounded-md mt-2">
<div class="flex items-center">
<div><input type="checkbox" class="mr-2" /></div>
<div>Required?</div>
</div>
</div>
</div>
<div v-else-if="element.name == 'Divider'">
<div class="flex items-center">
<div class="flex-grow border-t border-black mx-4"> </div>
<div class="flex ">
<div class="cursor-pointer">
<i class="handle las la-arrows-alt la-2x mr-2"></i>
</div>
<div #click="remove(index)">
<i class="las la-trash-alt text-red-800 la-2x cursor-pointer"></i>
</div>
</div>
</div>
</div>
</div>
</template>
</draggable>
</div>
</div>
</div>
</template>
See Clone method which assigns a random number as the id
<script>
import draggable from "vuedraggable";
export default {
name: "Survey",
components: {
draggable,
},
data() {
return {
drag: false,
componentsList: [
{ name: "Single Line of Text", type: "question", text: "", id: 1 },
{ name: "Multiple Choice", type: "question", text: "", id: 2 },
{ name: "Matrix", type: "question", text: "", id: 3 },
{ name: "Open Ended", type: "question", text: "", id: 4 },
{ name: "Divider", type: "component", id: 9 },
],
questionsList: [],
multipleChoiceList: [
{text: "text A", type:"choice", question:"32"},
{text: "text B", type:"choice", question:"1"},
{text: "text A", type:"choice", question:"2"} ]
};
},
methods: {
onEnd: function(evt) {
console.log(evt);
},
log: function(evt) {
console.log(evt);
},
addChoice(id) {
this.multipleChoiceList.push({ text: "Choice " + id, type: "choice", question:id });
console.log(this.multipleChoiceList);
},
remove(index) {
this.questionsList.splice(index, 1);
},
cloneItem({ id, name, type }) {
return {
name: name,
id: Math.ceil(Math.random()*100),
text: "",
type: type,
};
}
},
mounted() {
// console.log("mounted");
},
};
</script>

https://github.com/SortableJS/Vue.Draggable/issues/687#issuecomment-1153083717
I just answered to a similar question on github.
Not sure would this help as Vue.Draggable and vue.draggable.next is slightly different.

Related

How to position the dropdown to top of the grid elements

I tried to position the dropdown to the top of the page using Tailwind CSS and z-index.
But it goes behind of other elements in the grid
image
Code Snipets
<div class="flex flex-col gap-y-4">
<h1 class="text-3xl font-semibold text-left font-display sm:text-4xl">
Following
</h1>
<div class="flex flex-col w-full h-full gap-4 p-4 bg-white border border-gray-200 rounded shadow-md">
<h1 class="mb-3 text-xl font-semibold text-left font-display">
Legislators
</h1>
<div class="flex flex-col items-between">
<div class="relative z-10 grid gap-4 mb-5 xxs:grid-cols-1 xs:grid-cols-1 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-3">
<FollowingCard
v-for="govId in legislatorsFollowed"
:key="govId"
class="w-full sm:w-auto"
:legor-id="govId"
/>
</div>
</div>
</div>
FollowingCard.vue
person
{{ name }}
{{ role }} | {{ party }} | {{ state }} of {{ country }} {{showDropdown}}
more_vert
<div v-if="showDropdown" class="absolute top-0 left-0 z-40 flex flex-col py-1 mt-8 overflow-y-auto bg-white border border-gray-200 rounded-md shadow-sm max-h-40" data-testid="sessionDropdownBtn">
<button
v-for="session in topics"
:key="session"
class="relative z-50 flex items-center justify-start w-full px-4 py-2 text-sm text-left capitalize hover:bg-gray-100 font-body min-w-max"
>
{{ session }}
</button>
</div>
</button>
</div>
</transition>
</div>

Why I cant parse the {{task}} variable inside the v-for in the task-panel child?

The for loop is working properly. When I add a new task panel shows but the {{task}} variable inside the component is not showing. It must be something with the component template.
<span class="col-span-3 bg-blue-200 p-2">{{task}}</span>
I have left all the code down here maybe is something that I don't see.
Any idea? Thanks
<body>
<div id="app">
<task-input></task-input>
</div>
<script>
let app = Vue.createApp({ });
app.component(
'task-input',
{
template:
`<div class=" container grid grid-cols-4 mb-5 border-2 border-gray-600 center mt-5 mx-auto bg-gray-400 ">
<input id="taskInput" v-model="task" class="bg-white col-span-3 p-3 text-black font-bold" type="text" placeholder="What you will do next" />
<button #click="addTask()" class="text-white font-extrabold uppercase">Add new task</button>
</div>
<div class="container container mx-auto rounded-top-lg">
<div class=" bg-gray-200 border-2 border-gray-600 center column-1 container mx-auto mt-5 mx-auto rounded-top-lg">
<h1 class="font-sans text-2xl text-center text-white bg-gray-500 uppercase font-extrabold px-4 py-4">
{{title}}
</h1>
<ul class="bg-white">
<task-panel v-for="task in tasks"/>
</ul>
</div>
</div>`,
data() {
return {
title:"Here is a nice title",
task: '',
tasks: [],
}
},
components:['task-panel'],
methods:{
addTask(){
this.tasks.push(this.task);
this.task='';
console.log(this.tasks);
}
}
},
);
app.component('task-panel',{
template:
`<li class="grid bg-gray-200 mt-1">
<div class="grid grid-cols-4">
<span class="col-span-3 bg-blue-200 p-2">{{task}}</span>
<span class="col-span-1 text-center self-center uppercase font-bold">test</span>
</div>
<div class="flex justify-end bg-gray-300 p-1">
<button class="bg-blue-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">To Do</button>
<button class="bg-green-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">Done</button>
<button class="bg-red-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">Blocked</button>
</div>
</li>
`,
data() {
return { }
},
props: ['tasks', 'modelValue'],
computed:{
tasks:{
get(){
return this.tasks;
}
}
}
});
app.mount('#app');
</script>
</body>
The v-for is only in the scope of the parent component. The v-for's iterator prop does not get automatically passed into the task-panel.
You need to explicitly bind the iterator prop to task-panel's prop:
👇
<task-panel v-for="task in tasks" :task="task" />
Also, the prop in task-panel should have the same name. It's currently spelled tasks (with an s at the end). The last s should be removed so that it matches what the template is rendering:
// props: ['tasks', ⋯],
props: ['task', ⋯],
<script src="https://unpkg.com/vue#3.2.31/dist/vue.global.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<div id="app">
<task-input></task-input>
</div>
<script>
let app = Vue.createApp({ });
app.component(
'task-input',
{
template:
`<div class=" container grid grid-cols-4 mb-5 border-2 border-gray-600 center mt-5 mx-auto bg-gray-400 ">
<input id="taskInput" v-model="task" class="bg-white col-span-3 p-3 text-black font-bold" type="text" placeholder="What you will do next" />
<button #click="addTask()" class="text-white font-extrabold uppercase">Add new task</button>
</div>
<div class="container container mx-auto rounded-top-lg">
<div class=" bg-gray-200 border-2 border-gray-600 center column-1 container mx-auto mt-5 mx-auto rounded-top-lg">
<h1 class="font-sans text-2xl text-center text-white bg-gray-500 uppercase font-extrabold px-4 py-4">
{{title}}
</h1>
<ul class="bg-white">
<task-panel v-for="task in tasks" :task="task" />
</ul>
</div>
</div>`,
data() {
return {
title:"Here is a nice title",
task: '',
tasks: [],
}
},
components:['task-panel'],
methods:{
addTask(){
this.tasks.push(this.task);
this.task='';
console.log(this.tasks);
}
}
},
);
app.component('task-panel',{
template:
`<li class="grid bg-gray-200 mt-1">
<div class="grid grid-cols-4">
<span class="col-span-3 bg-blue-200 p-2">{{task}}</span>
<span class="col-span-1 text-center self-center uppercase font-bold">test</span>
</div>
<div class="flex justify-end bg-gray-300 p-1">
<button class="bg-blue-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">To Do</button>
<button class="bg-green-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">Done</button>
<button class="bg-red-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">Blocked</button>
</div>
</li>
`,
data() {
return { }
},
props: ['task', 'modelValue'],
});
app.mount('#app');
</script>

b-table render all the data without respecting the fields

I am building a project using laravel and Vue JS to create a list of companies with pagination etc..
I am using bootstrap-table and the problem the table render all the data without respecting the fields that I am giving as a param. I want to use scope field to show a custom css inside every row. I use the same table with other data it works fine.
This is the component code
<template>
<div class="row">
<div class="col-lg-3 mt-lg-5">
<div class="card bord-rad-5">
<div class="card-header purple-background top-borders">
<h4
class="title-align font-montserrat text-light white-text-color mt-3 position-filter"
>
Filter
</h4>
</div>
<div class="card-body">
<div class="d-flex flex-column">
<div
class="gray-text-color font-weight-bold font-montserrat-regular mb-2"
>
<h5>{{ $t('labels.frontend.filters.companyName') }}</h5>
</div>
<div class="form-group">
<b-form-group class="ml-1">
<b-input-group>
<b-form-input v-model="filter" placeholder="Type to search">
</b-form-input>
<b-input-group class="mr-2">
<b-button
class="mr-left-90 mr-4 mt-2 font-montserrat-regular"
:disabled="!filter"
#click="filter = ''"
>
{{ $t('labels.frontend.companies.clear') }}
</b-button>
</b-input-group>
</b-input-group>
</b-form-group>
</div>
<div
class="gray-text-color font-weight-bold font-montserrat-regular mt-2 mb-2"
>
<h5>{{ $t('labels.frontend.filters.companyType') }}</h5>
</div>
<div class="form-check form-check-inline mt-1 mb-1">
<input
class="form-check-input"
type="checkbox"
id="ac1"
value="AssemblyCompany"
/>
<label
class="form-check-label gray-text-color font-weight-bold font-montserrat-thin"
for="ac1"
>
{{ $t('labels.frontend.filters.dismantling') }}
</label>
</div>
<div class="form-check form-check-inline mt-1 mb-1">
<input
class="form-check-input"
type="checkbox"
id="gd1"
value="garagebusiness"
/>
<label
class="form-check-label gray-text-color font-weight-bold font-montserrat-thin"
for="gd1"
>
{{ $t('labels.frontend.filters.garage') }}
</label>
</div>
<div class="form-check form-check-inline mt-1 mb-1">
<input
class="form-check-input"
type="checkbox"
id="rb1"
value="RevisionCompany"
/>
<label
class="form-check-label gray-text-color font-weight-bold font-montserrat-thin"
for="rb1"
>
{{ $t('labels.frontend.filters.revision') }}
</label>
</div>
</div>
</div>
</div>
</div>
<div class="mt-5 col-lg-9">
<div class="card-header purple-background bord-top-lr-5">
<b-row class="mt-2">
<b-col>
<h4 class="title-align font-montserrat text-light white-text-color">
{{ items.count }} {{ $t('labels.frontend.companies.results') }}
</h4>
</b-col>
<b-form-group label-cols-sm="3" class="mb-2 w-25 mr-4">
<b-form-select v-model="perPage" :options="pageOptions">
</b-form-select>
</b-form-group>
</b-row>
</div>
<div class="card-body white-bg">
<div class="grid-x grid-padding-x m-2 border-0">
<div class="border-0 mb-2">
<b-table
striped
hover
:items="items.data"
:fields="columns"
:filter="filter"
:current-page="currentPage"
:per-page="perPage"
:outlined="outlined"
responsive
>
<template slot="name" class="m-3" slot-scope="item">
<h5 class="title-align font-montserrat" style="color: #5b2557">
<a :href="data.item.url" :title="data.item.name">
{{ data.item.name }}
</a>
</h5>
<div class="row">
<div class="col">
<p
class="gray-text-color font-montserrat-thin font-weight-bold"
>
{{ data.item.street }}
{{ data.item.building_nr }} {{ data.item.postal }}
{{ data.item.city }} {{ data.item.state }}
</p>
</div>
<div class="col ml-lg-5">
<p
class="font-montserrat-thin blue-light-color font-weight-bold"
>
T. {{ data.item.phone }}<br />
<a
:href="data.item.website"
target="_blank"
:title="data.item.name"
class="gray-text-color"
>
{{ $t('labels.frontend.companies.goTo') }}
</a>
</p>
</div>
<div class="col ml-lg-5">
<a
class="font-montserrat-regular"
:href="
$app.route('frontend.companies.show', data.item.slug)
"
style="color: #74aee0"
>
{{ $t('labels.frontend.companies.moreInfo') }} »
</a>
</div>
</div>
<button
class="mb-3 blue-light-bg btn bord-rad-5 white-text-color font-montserrat-regular"
href="#"
>
{{ $t('labels.frontend.companies.stock') }}
</button>
<br />
</template>
</b-table>
<b-row>
<b-col md="6" class="my-1">
<b-pagination
v-model="currentPage"
:total-rows="totalRows"
:per-page="perPage"
class="my-0"
></b-pagination>
</b-col>
</b-row>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SearchCompaniesTable',
props: {
companyName: {
type: String,
required: false,
default: () => ''
}
},
data() {
return {
filter: null,
totalRows: 1,
currentPage: 1,
perPage: 10,
pageOptions: [5, 10, 25],
outlined: true,
columns: [
{
field: 'name',
label: 'Name'
}
],
items: []
}
},
computed: {
rows() {
return Object.keys(this.items).length
}
},
mounted() {
axios.get('/companies/search').then(response => {
this.items = response.data
this.totalRows = this.items.count
console.log(this.fields)
})
}
}
</script>
<style>
.hidden_header {
display: none;
}
thead {
border: none !important;
}
tbody {
border: none !important;
border-color: white;
}
table {
border: none !important;
}
th {
border: none !important;
}
tr {
border: none !important;
}
td {
border: none !important;
}
.mr-left-90 {
margin-left: 68px;
}
.position-filter {
position: relative;
top: -8px;
}
</style>
could you please help me to find a solution for that ?
Here you can find the code for the component
<template>
<div class="row">
<div class="col-lg-3 mt-lg-5">
<div class="card bord-rad-5">
<div class="card-header purple-background top-borders">
<h4
class="title-align font-montserrat text-light white-text-color mt-3 position-filter"
>
Filter
</h4>
</div>
<div class="card-body">
<div class="d-flex flex-column">
<div
class="gray-text-color font-weight-bold font-montserrat-regular mb-2"
>
<h5>{{ $t('labels.frontend.filters.companyName') }}</h5>
</div>
<div class="form-group">
<b-form-group class="ml-1">
<b-input-group>
<b-form-input v-model="filter" placeholder="Type to search">
</b-form-input>
<b-input-group class="mr-2">
<b-button
class="mr-left-90 mr-4 mt-2 font-montserrat-regular"
:disabled="!filter"
#click="filter = ''"
>
{{ $t('labels.frontend.companies.clear') }}
</b-button>
</b-input-group>
</b-input-group>
</b-form-group>
</div>
<div
class="gray-text-color font-weight-bold font-montserrat-regular mt-2 mb-2"
>
<h5>{{ $t('labels.frontend.filters.companyType') }}</h5>
</div>
<div class="form-check form-check-inline mt-1 mb-1">
<input
class="form-check-input"
type="checkbox"
id="ac1"
value="AssemblyCompany"
/>
<label
class="form-check-label gray-text-color font-weight-bold font-montserrat-thin"
for="ac1"
>
{{ $t('labels.frontend.filters.dismantling') }}
</label>
</div>
<div class="form-check form-check-inline mt-1 mb-1">
<input
class="form-check-input"
type="checkbox"
id="gd1"
value="garagebusiness"
/>
<label
class="form-check-label gray-text-color font-weight-bold font-montserrat-thin"
for="gd1"
>
{{ $t('labels.frontend.filters.garage') }}
</label>
</div>
<div class="form-check form-check-inline mt-1 mb-1">
<input
class="form-check-input"
type="checkbox"
id="rb1"
value="RevisionCompany"
/>
<label
class="form-check-label gray-text-color font-weight-bold font-montserrat-thin"
for="rb1"
>
{{ $t('labels.frontend.filters.revision') }}
</label>
</div>
</div>
</div>
</div>
</div>
<div class="mt-5 col-lg-9">
<div class="card-header purple-background bord-top-lr-5">
<b-row class="mt-2">
<b-col>
<h4 class="title-align font-montserrat text-light white-text-color">
{{ items.count }} {{ $t('labels.frontend.companies.results') }}
</h4>
</b-col>
<b-form-group label-cols-sm="3" class="mb-2 w-25 mr-4">
<b-form-select v-model="perPage" :options="pageOptions">
</b-form-select>
</b-form-group>
</b-row>
</div>
<div class="card-body white-bg">
<div class="grid-x grid-padding-x m-2 border-0">
<div class="border-0 mb-2">
<b-table
striped
hover
:items="items.data"
:fields="columns"
:filter="filter"
:current-page="currentPage"
:per-page="perPage"
:outlined="outlined"
responsive
>
<template slot="name" class="m-3" slot-scope="item">
<h5 class="title-align font-montserrat" style="color: #5b2557">
<a :href="data.item.url" :title="data.item.name">
{{ data.item.name }}
</a>
</h5>
<div class="row">
<div class="col">
<p
class="gray-text-color font-montserrat-thin font-weight-bold"
>
{{ data.item.street }}
{{ data.item.building_nr }} {{ data.item.postal }}
{{ data.item.city }} {{ data.item.state }}
</p>
</div>
<div class="col ml-lg-5">
<p
class="font-montserrat-thin blue-light-color font-weight-bold"
>
T. {{ data.item.phone }}<br />
<a
:href="data.item.website"
target="_blank"
:title="data.item.name"
class="gray-text-color"
>
{{ $t('labels.frontend.companies.goTo') }}
</a>
</p>
</div>
<div class="col ml-lg-5">
<a
class="font-montserrat-regular"
:href="
$app.route('frontend.companies.show', data.item.slug)
"
style="color: #74aee0"
>
{{ $t('labels.frontend.companies.moreInfo') }} »
</a>
</div>
</div>
<button
class="mb-3 blue-light-bg btn bord-rad-5 white-text-color font-montserrat-regular"
href="#"
>
{{ $t('labels.frontend.companies.stock') }}
</button>
<br />
</template>
</b-table>
<b-row>
<b-col md="6" class="my-1">
<b-pagination
v-model="currentPage"
:total-rows="totalRows"
:per-page="perPage"
class="my-0"
></b-pagination>
</b-col>
</b-row>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SearchCompaniesTable',
props: {
companyName: {
type: String,
required: false,
default: () => ''
}
},
data() {
return {
filter: null,
totalRows: 1,
currentPage: 1,
perPage: 10,
pageOptions: [5, 10, 25],
outlined: true,
columns: [
{
field: 'name',
label: 'Name'
}
],
items: []
}
},
computed: {
rows() {
return Object.keys(this.items).length
}
},
mounted() {
axios.get('/companies/search').then(response => {
this.items = response.data
this.totalRows = this.items.count
console.log(this.fields)
})
}
}
</script>
What mistake i am doing and thank you for answering
In your first code snippet your style is not using the scoped attribute, which may mean the rest of your project is doing he same thing. This could mean that your CSS is being overwritten at the global level, If you inspect the element after render can you see if your CSS is being overwritten somewhere.
Also, if you happen to be using SCSS the bootstrap-vue library supports it very well and I have found it to be easier to adjust the bootstrap css easier.
I fixed the problem by changing the code inside the template tag from <template slot="name" slot-scope="item"> to <template v-slot:cell(name)="data">

How to add vue #click event in tooltip title content?

I will need to add #click event handler to the tooltip content. so the user can click on the tooltip to get more details.
simply writing #click will not work.
Vue full Calendar code here I use the eventRender event to attach the tooltips.
<FullCalendar
ref="fullCalendar"
:customButtons="this.customButtons"
:eventLimit="this.config.eventLimit"
:header="false"
:events="events"
:plugins="calendarPlugins"
:defaultDate="date"
#datesRender="setDatepickerValue"
#eventRender="getEventDetailsPopup"
defaultView="dayGridMonth"
/>
and the event rendered event handler code mentioned below
methods: {
getEventDetailsPopup: function(mouseInfo) {
var tooltip = new Tooltip(mouseInfo.el, {
title: `
<div class="container max-w-sm mx-auto overlay cursor-pointer rounded">
<div class="centered flex items-center m-4 w-full ">
<div class="w-1/3 h-12 ">
<i class="fa fa-heart" aria-hidden="true"></i>
<span class="text-white">0</span>
</div>
<div class="w-1/3 h-12">
<i class="fa fa-comment" aria-hidden="true"></i>
<span class="text-white">0</span>
</div>
<div class="w-1/3 h-12">
<i class="fa fa-retweet" aria-hidden="true"></i>
<span class="text-white">0</span>
</div>
<div class="w-1/3 h-12 ">
<i class="fa fa-location-arrow" aria-hidden="true"></i>
<span class="text-white">0</span>
</div>
</div>
</div>
<div class="container bg-white max-w-1 mx-auto">
<div class="max-w-sm rounded overflow-hidden shadow-lg">
<img
class="w-full h-32"
src="https://tailwindcss.com/img/card-top.jpg"
alt="Sunset in the mountains"
>
<div class="px-6 py-4 ">
<div class="font-bold text-xl mb-2">${mouseInfo.event.title}</div>
<p class="text-gray-700 text-base">
${mouseInfo.event.extendedProps.description}
</p>
</div>
<div class="px-6 py-2 bg-blue-900 h-9">
<span class="inline-block bg-gray-200 rounded-full px-3 text-sm font-semibold text-gray-700 mr-2">
Autoschedule</span>
</div>
</div>
</div>`,
placement: "right",
trigger: "hover",
html: true,
container: "body",
delay: { show: 100 },
template: `<div class="tooltip calendar" role="tooltip">
<div class="tooltip-arrow x-arrow"></div>
<div class="tooltip-inner"></div>
</div>`
});
},
callEventDetailPopup: function() {
console.log("called");
},
Need to add a click handler on the title content.
try this
<FullCalendar #eventClick="eventClick" />

Is there a way to get the data from multiple selects as array?

I'm currently stuck on a task on VueJS. Basically I'm trying to create an array from multiple select inside a form to get all the data as an array or Object to process it further. I just searched but got no results or an idea on how to solve my issue.
Parent Component
<template>
<div id="product" class="mt-12">
<div class="flex flex-wrap mb-4">
<div class="w-1/2 pr-12">
<img src="https://placehold.it/800" alt="">
</div>
<div class="w-1/2">
<div class="flex justify-between content-center h-12 mb-4">
<div class="text-gray-700 py-2">
<h2 v-if="product.brand" class="leading-none font-bold text-sm">{{ product.brand }}</h2>
<h1 class="text-xl leading-snug">{{ product.name }}</h1>
</div>
<div class="text-gray-700 py-2">
<p class="text-xl font-bold leading-none">{{ product.price }}</p>
<p class="text-xs text-right leading-none">Inkl. 19% MwSt.</p>
</div>
</div>
<div class="divider bg-gray-400 mt-4 mb-4" />
<div id="variations">
<form action="">
<ProductVariation v-for="(variations, type) in product.variations" :type="type" :variations="variations" :key="type" v-model="form.variation"/>
<div class="flex w-full">
<button class="w-full leading-none bg-blue-500 hover:bg-blue-600 text-white py-2 rounded" type="submit">Add to cart</button>
</div>
</form>
</div>
</div>
</div>
</div>
</template>
<script>
import ProductVariation from '#/components/products/ProductVariation'
export default {
data () {
return {
product: null,
form: {
variation: null
}
}
},
components: {
ProductVariation
},
async asyncData({ params, app }) {
let response = await app.$axios.$get(`products/${params.slug}`)
return {
product: response.data
}
}
}
</script>
ProductVariation Component
<template>
<div class="flex mb-4">
<div class="w-full">
<label class="block text-gray-700 w-full text-sm font-bold">{{ type }}</label>
<select class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight" :name="type">
<option value="0">Please select</option>
<option v-for="variation in variations" :key="variation.id" :value="variation.id">{{ variation.name }} <span>( +{{ variation.price }} )</span></option>
</select>
</div>
</div>
</template>
<script>
export default {
props: {
type: {
required: true,
type: String
},
variations: {
required: true,
type: Array
}
},
}
</script>