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" />
Related
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>
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.
I am really new in Vue and I am getting this error in my code which is quite basic navbar
<template>
<nav
class="navbar navbar-expand-lg bg-dark navbar-light d-none d-lg-block"
id="templatemo_nav_top"
>
<div class="container text-light">
<div class="w-100 d-flex justify-content-between">
<div v-for="info in contactInfos">
<i :class="{info.icon}"></i>
<a class="navbar-sm-brand text-light text-decoration-none" href="#">{{info.contact}}</a>
</div>
<div>
<a class="text-light" href="#" target="_blank" rel="sponsored"
><i class="fab fa-facebook-f fa-sm fa-fw me-2"></i
></a>
<a class="text-light" href="#" target="_blank"
><i class="fab fa-instagram fa-sm fa-fw me-2"></i
></a>
<a class="text-light" href="#" target="_blank"
><i class="fab fa-twitter fa-sm fa-fw me-2"></i
></a>
<a class="text-light" href="#" target="_blank"
><i class="fab fa-linkedin fa-sm fa-fw"></i
></a>
</div>
</div>
</div>
</nav>
</template>
<script>
export default {
data() {
return {
contactInfos: [
{ icon: 'fa fa-envelope mx-2', contact: 'info#company.com'},
{ icon: 'fa fa-phone mx-2', contact: '000-000-0000'},
]
};
},
};
</script>
So I dont know what I am doing wrong, I basically want to show contact info inside the div.
Thanks...
I am new in Vue. In my code I gonna use a lot of same looking container and all of them should have slider page. For now when I clicking on top of container all slider-pages is coming out. I am understand,I should add id(ref) to each container. But I still cant get how to use it. Huge Thanks for any help or advice.
<template>
<div #click="shotList" ref="123">
<span>
<div
class="d-flex flex-row top-row justify-content-center mt-5"
style="z-index: 111 !important"
>
<div class="flex-row d-flex top-size">
<span class="col text-left" style="margin-top: -2px"
>21:40-23:00</span
>
<span class="col-9 text-right" style="margin-top: -2px"
>UFC 256 MMA</span
>
</div>
</div>
<div
class="d-flex flex-row justify-content-center"
style="z-index: 111 !important"
>
<div class="flex-row d-flex bottom-size">
<span class="col-5 bottom-size-white">Habib</span>
<span class="col-2 bottom-size-green"
>5%
<p class="bottom-p">Volatility</p>
</span>
<span class="col-5 bottom-size-black">Connor</span>
</div>
</div>
</span>
<ListBase :title="[{ text: `3`, value: `2` }]" />
</div>
<div #click="shotList" ref="125">
<span>
<div
class="d-flex flex-row top-row justify-content-center mt-5"
style="z-index: 111 !important"
>
<div class="flex-row d-flex top-size">
<span class="col text-left" style="margin-top: -2px"
>21:40-23:00</span
>
<span class="col-9 text-right" style="margin-top: -2px"
>UFC 256 MMA</span
>
</div>
</div>
<div
class="d-flex flex-row justify-content-center"
style="z-index: 111 !important"
>
<div class="flex-row d-flex bottom-size">
<span class="col-5 bottom-size-white">Habib</span>
<span class="col-2 bottom-size-green"
>5%
<p class="bottom-p">Volatility</p>
</span>
<span class="col-5 bottom-size-black">Connor</span>
</div>
</div>
</span>
<ListBase :title="[{ text: `3`, value: `2` }]" />
</div>
</template>
<script>
export default {
name: "take",
data() {
return {
show: false,
};
},
methods: {
shotList() {
this.show = !this.show;
if (this.show) {
this.$emit("openList");
} else {
this.$emit("closeList");
}
},
spaceCheck(event) {
let x = event.pageX;
let y = event.pageY;
console.log(x, y);
},
},
};
</script>
I tried everything to make the navigation links hide when I clicked but it didn't worked. Here my Header.vue file.
<template>
<nav class="navbar is-dark is-fixed-top">
<div class="container">
<div class="navbar-brand">
<router-link to="/" class="navbar-item">
<img src="../../assets/logo.png" width="">
</router-link>
<a role="button"
:class="{ 'is-active': ShowMenu }"
class="navbar-burger burger"
#click="toggleMenu()"
aria-label="menu"
aria-expanded="false">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div :class="{ 'is-active': ShowMenu }"
class="navbar-menu">
<div class="navbar-start">
<router-link to="/" class="navbar-item">Home</router-link>
<router-link to="/about" class="navbar-item">About</router-link>
</div>
<div class="navbar-end">
<div class="navbar-item">
<div class="field is-grouped">
<p class="control">
<router-link to="/login" class="button is-dark">
<span><i class="fa fa-lock"></i> Login</span>
</router-link>
</p>
<p class="control">
<router-link to="/register" class="button is-light">
<span><i class="fa fa-user"></i> Register</span>
</router-link>
</p>
</div>
</div>
</div>
</div>
</div>
</nav>
Here's the JS codes. Navigation are working when a click the links but the only problem I have is that it didn't automatically hide.
export default {
name: "Header",
data() {
return {
ShowMenu: false,
NavigationItems: true,
NavigationItems: false
}
},
methods: {
toggleMenu: function() {
this.ShowMenu = !this.ShowMenu
},
toggleNavItem: function() {
false
}
}
}
Try
<a v-if='!ShowMenu' role="button" ...
instead of using CSS
You shouldn't use v-if it will "kill" the element in the dom, but if you only want to toggle it use v-show width !ShowMenu like Steven explained.
And if you want to use a CSS class: do you have a class called is-active and is the default behavior of .burger display: none;? If you want to stay on this solution please provide us your CSS.