Vue.js vuetifyjs Calendar not dispaying day events - vue.js

I have a working calendar that can change based on the type property. I am able to display information in the calendar header but day events seem to be a problem.
My vue.js vuetify calendar does not display day events. It is set to display as type 'week'. I am working from the following example.
export default {
data: () => ({
todayDate: new Date().toISOString().substr(0, 10) /*'YYYY-MM-DD'*/ ,
type: 'week',
events: [{
title: 'Weekly Meeting',
date: '2019-02-26',
time: '09:00',
duration: 45
},
{
title: 'Mash Potatoes',
date: '2019-02-28',
time: '12:30',
duration: 180
}
]
}),
computed: {
eventsMap() {
const map = {};
this.events.forEach(e => (map[e.date] = map[e.date] || []).push(e));
return map
}
}
}
</script>
<v-calendar ref="calendar" :type="type" v-model="todayDate" :now="todayDate" :value="todayDate" color="primary">
<template slot="dayBody" slot-scope="{ date, timeToY, minutesToPixels }">
<template v-for="event in eventsMap[date]">
<div
v-if="event.time"
:key="event.title"
v-html="event.title"
></div>
</template>
</template>
</v-calendar>

You are probably missing event styles which are included in docs. Copy styling and edit your html file
.my-event {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
border-radius: 2px;
background-color: #1867c0;
color: #ffffff;
border: 1px solid #1867c0;
font-size: 12px;
padding: 3px;
cursor: pointer;
margin-bottom: 1px;
left: 4px;
margin-right: 8px;
position: relative;
&.with-time {
position: absolute;
right: 4px;
margin-right: 0px;
}
}
</script>
<v-calendar ref="calendar" :type="type" v-model="todayDate" :now="todayDate" :value="todayDate" color="primary">
<template slot="dayBody" slot-scope="{ date, timeToY, minutesToPixels }">
<template v-for="event in eventsMap[date]">
<div
v-if="event.time"
:key="event.title"
:style="{ top: timeToY(event.time) + 'px', height: minutesToPixels(event.duration) + 'px' }"
class="my-event with-time"
v-html="event.title"
></div>
</template>
</template>
</v-calendar>

One of the reason could be Events are not displaying because you are missing color property in Events objects. Without color property, Events are present but not visible because by default color is white.
{
color: 'indigo',
name: 'Weekly Meeting',
date: '2019-02-26',
time: '09:00',
duration: 45
},

Related

Vuejs Transition

I want to add transition when the values get changes but cannot accomplish it. I need to change the background when the values get updated.
Can anyone help me out?
Codesandbox Link - Vuejs Transition
<template>
<div id="app">
<div class="box">
<div v-if="change > 0">
<transition name="increase">
<span>+ {{ amount }} </span></transition
>
</div>
<div v-else-if="change < 0">
<transition name="decrease">
<span>- {{ amount }}</span>
</transition>
</div>
<div v-else>{{ amount }}</div>
</div>
<br />
<button #click="generate">Update</button>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
change: 2,
amount: 100,
};
},
methods: {
generate() {
var amounts = [100, 110, 85, 75, 190];
let changes = [-1.2, -5, 2, 5, 1, 7];
this.amount = amounts[Math.floor(Math.random() * amounts.length)];
this.change = changes[Math.floor(Math.random() * changes.length)];
},
},
created() {},
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.box {
width: 100px;
margin: 0 auto;
border: 1px solid #ddd;
padding: 1em 2em;
}
#keyframes higher {
50% {
background: rgba(50, 199, 135, 0.2);
color: #32c787;
}
}
#keyframes lower {
50% {
background: rgba(255, 86, 82, 0.2);
color: #ff5652;
}
}
.increase-enter {
animation: higher 0.5s;
}
.decrease-enter {
animation: lower 0.5s;
}
</style>
P.S - Ignore this, posted because my text is too short. IT is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.
You can make use of key to inform transition there is a difference of the element so it can trigger the animation again.
Also, use the -active class to apply animation during entering phase.
https://codesandbox.io/s/transition-forked-vg5pu?file=/src/App.vue
<transition name="increase">
<span :key="amount + change">+ {{ amount }}</span>
</transition>
...
.increase-enter-active {
animation: higher 0.5s;
}

Vuetify v-card elevation doesn't show up, flat attribute does

I'm trying to change the elevation of my v-cards in vuetify in my index.vue page but the changes dont show up, right now the code for my card reads: <v-card class="cards" elevation="0" shaped> but I tried it with class="elevation-0" as well. It doesn't work with any elevation but if I e.g. use the attribute: ``` the changes show up.
In my other pages the elevation attribute works (in my _slug.vue page), just in the index.vue page it doesn't. I also tried to change move the code of the cards to an own component but it doesn't work as well.
The Component in my index.vue file:
<template>
<NuxtLink :to="'/' + Link">
/* This is the card I'm talking about */
<v-card class="cards" elevation="0" shaped>
<img class="thumbnail" :src="Image" />
<h3 class="video-title">{{ Title }}</h3>
<h3 class="video-type">Most {{ Name }}:</h3>
</v-card>
</NuxtLink>
</template>
<script>
export default {
name: "ThumbnailCard",
props: {
Image: String,
Title: String,
Link: String,
Name: String,
},
};
</script>
<style scoped>
.cards {
margin-top: 15vh;
margin-left: 1vw;
margin-right: 1vw;
height: 30vh;
text-align: center;
}
.thumbnail {
width: 100%;
height: 30vh;
}
.video-type {
position: absolute;
top: 0;
left: 0;
right: 0;
margin-top: 9vh;
}
.video-title {
position: absolute;
top: 0;
left: 0;
right: 0;
margin-top: 18vh;
}
#media only screen and (max-width: 599px) {
.cards {
margin-top: 2vh;
margin-bottom: 2vh;
margin-left: 15vw;
margin-right: 15vw;
height: 14.5vh;
}
.thumbnail {
height: 14.5vh;
}
.video-type {
margin-top: 4vh;
}
.video-title {
margin-top: 8vh;
}
}
</style>
The whole code for my index.vue:
<template id="main">
<div>
<div id="title-section">
<h1 id="title">Title</h1>
<h2 id="description">This Site is awesome, have a look</h2>
</div>
<v-container id="content-wrapper">
<v-row no-gutters>
<v-col cols="12" sm="4">
<ThumbnailCard
:Image="recentImage"
:Title="recentTitle"
:Link="recentLink"
Name="Recent"
/>
</v-col>
<v-col cols="12" sm="4">
<ThumbnailCard
:Image="popularImage"
:Title="popularTitle"
:Link="popularLink"
Name="Popular"
/>
</v-col>
<v-col cols="12" sm="4">
<ThumbnailCard
:Image="relevantImage"
:Title="relevantTitle"
:Link="relevantLink"
Name="Recent"
/>
</v-col>
</v-row>
</v-container>
</div>
</template>
<script>
import ThumbnailCard from "#/components/global/ThumbnailCard";
export default {
name: "index",
components: {
ThumbnailCard: ThumbnailCard,
},
async asyncData({ $content, params }) {
const articles = await $content("articles")
.only(["date", "slug", "title", "img"])
.fetch();
const datesArr = articles.map((a) => {
return new Date(a.date).getTime() / 1000;
});
const recentTitle = articles[datesArr.indexOf(Math.min(...datesArr))].title;
const recentLink = articles[datesArr.indexOf(Math.min(...datesArr))].slug;
const recentImage = articles[datesArr.indexOf(Math.min(...datesArr))].img;
const popularTitle = articles[0].title;
const popularLink = articles[0].slug;
const popularImage = articles[0].img;
const relevantTitle = articles[0].title;
const relevantLink = articles[0].slug;
const relevantImage = articles[0].img;
return {
recentTitle,
recentLink,
recentImage,
popularTitle,
popularLink,
popularImage,
relevantTitle,
relevantLink,
relevantImage,
};
},
};
</script>
<style>
html {
overflow-y: auto;
}
::-webkit-scrollbar {
width: 5px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background: #888;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
#title-section {
background: black;
width: 100%;
height: 40vh;
text-align: center;
}
#title {
color: white;
font-size: 4rem;
}
#description {
color: white;
}
#content-wrapper {
height: 60vh;
width: 100%;
}
</style>
For anyone having the same problem: I forgot the <v-app> component which somehow resulted in the elevation attribute not working
the flat attribute works well to remove elevation from most vuetify components

Custom switch component with v-model doesn't work

trying to do my custom Switch component in VueJS following these manuals Using v-model on Components, Adding v-model Support to Custom Vue.js Components but something wrong and it doesn't work.
My SwitchTest component:
<template>
<div>
<input type="checkbox" :id="_uid"
:value="value"
#input="updateData"
class="checkbox">
<label :for="_uid" class="switch"></label>
</div>
</template>
<script>
export default {
props: ["value"],
data() {
return {};
},
methods: {
updateData($event) {
console.log($event.target.value);
this.$emit("input", $event.target.value);
}
}
};
</script>
<style scoped>
.switch {
position: relative;
display: inline-block;
width: 40px;
height: 20px;
background-color: rgba(0, 0, 0, 0.25);
border-radius: 20px;
transition: all 0.3s;
}
.switch::after {
content: "";
position: absolute;
width: 18px;
height: 18px;
border-radius: 50%;
background-color: white;
top: 1px;
left: 1px;
transition: all 0.3s;
}
.checkbox:checked + .switch::after {
left: 20px;
}
.checkbox:checked + .switch {
background-color: #7983ff;
}
.checkbox {
display: none;
}
</style>
And using SwitchTest component:
{{switch1}}
<SwitchTest v-model="switch1"/>
{{switch2}}
<SwitchTest v-model="switch2"/>
You can see the whole MVCE example here: https://codesandbox.io/s/ecstatic-meninsky-zx7w0?file=/src/App.vue:32-131
When I toggle checkbox, its value doesn't change.
Where am I wrong?
Thank you.
Checkboxes are a special case where they have two states (checked / unchecked) which can be translated to two values. Normally, this is simply true / false but since you've bound a single :value, you'll only ever get the same value each time.
Try binding the Boolean value prop to checked and emit a true / false value
<input
type="checkbox"
:checked="value"
:id="_uid"
#input="$emit('input', $event.target.checked)"
class="checkbox"
>

building a overlay fullscreen navbar in vue.js, by toggle navbar height from 0% to 100%

Trying to implement the overlay fullscreen menu with Vue.js, html/css/js is [this solution]https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_overlay2
But stuck with how to toggle div height from 0% to 100%. I did create 2 classes,
'navbar'
'navbar_open'
but I am not sure how to toggle between them in Vue. I could see that once #click triggered, the class="navbar navbar_open"
<div id="myNav" class="navbar navbar_open">
<div class="closebtn">
<i class="fa fa-times"></i>
</div>
<div class="navbar-content">
<a>Home</a><a>Contact</a>
</div>
</div>
below is the App.vue file,
<template>
<div id="app">
<!-- Banner/Header -->
<!-- Hamburger -->
<div id="myNav" class="navbar" :class="{ navbar_open: showNavbar }">
<div class="closebtn" v-on:click="showNavbar = !showNavbar">
<i class="fa fa-times"></i>
</div>
<div class="navbar-content">
<a>Home</a>
<a>Contact</a>
</div>
</div>
<div class="openbtn">
<i class="fa fa-bars" v-on:click="showNavbar = !showNavbar"></i>
</div>
<router-view />
</div>
</template>
<script>
export default {
data() {
return {
showNavbar: false
};
},
methods: {
toggleNavbar() {
this.showNavbar = !showNavbar;
},
setHeightValue(showNavbar) {
const heightValue = this.showNavbar ? '100%' : '0%';
return heightValue;
}
},
created() {
this.setHeightValue();
}
};
</script>
<style>
#import url('https://use.fontawesome.com/releases/v5.9.0/css/all.css');
.navbar_open {
width: 100%;
height: 100%;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.9);
overflow-y: hidden;
transition: 0.5s;
background-color: #2b4c72;
}
.navbar {
width: 100%;
height: 0%;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.9);
overflow-y: hidden;
transition: 0.5s;
background-color: #2b4c72;
}
.navbar-content {
position: relative;
top: 25%;
width: 100%;
text-align: center;
margin-top: 30px;
}
.navbar a {
padding: 8px;
text-decoration: none;
font-size: 36px;
color: #818181;
display: block;
transition: 0.3s;
}
.navbar a:hover,
.navbar a:focus {
color: #f1f1f1;
}
.navbar .closebtn {
position: absolute;
top: 20px;
left: 45px;
font-size: 60px;
color: white;
cursor: pointer;
}
.openbtn {
font-size: 30px;
}
#media screen and (max-height: 450px) {
.navbar {
overflow-y: auto;
}
.navbar a {
font-size: 20px;
}
.navbar .closebtn {
font-size: 40px;
top: 15px;
right: 35px;
}
}
</style>
I see that you have unused method toggleNavbar. You call setHeightValue only when your component is created and then never again (I think you can remove this method). This menu is not 100% height probably because you embedded this component in another container (<div id="app:...) which has smaller height so height: 100% will be 100% height of parent container. Instead of 100% you can use 100vh (vh - is a viewport unit and it will always take 100% viewport height [if 50vh then 50% of total viewport height]). You should also apply only navbar_open but now you are applying bot classes if your navbar is open: navabar navbar_open so you should add this classes conditionally:
:class="{ 'navbar_open': showNavbar, 'navbar': !showNavbar }"
You have also Two different buttons responsible for two different actions:
closebtn -> close navigation
openbtn -> open navigation
So you should create two different methods openNavigation closeNavigation
<div id="app">
<!-- Banner/Header -->
<!-- Hamburger -->
<div id="myNav" :class="{ 'navbar_open': showNavbar, 'navbar': !showNavbar }">
<div class="closebtn" #click="closeNavigation">
<i class="fa fa-times"></i>
</div>
<div class="navbar-content">
<a>Home</a>
<a>Contact</a>
</div>
</div>
<div class="openbtn">
<i class="fa fa-bars" #click="showNavigation"></i>
</div>
<router-view />
</div>
</template>
<script>
export default {
data() {
return {
showNavbar: false
};
},
methods: {
openNavigation() {
this.showNavbar = true;
},
closeNaviagation() {
this.showNavbar = false;
}
}
};
</script>
<style>
...
.navbar_open {
width: 100%;
height: 100vh; // <--- 100vh instead of 100%
position: fixed;
...
</style>

how to fix grid issue in vuejs

in vuejs i cant make grid css with v-for , i used template-grid-columns so i can have 3 divs in same row but the result was just one div in one row and this is not the result i want, so is there any optimal solution i can use, here is the code
this is the html part :
<template>
<div>
<div>
<select class="select" v-model="status">
<option value="onSale">onSale</option>
<option value="featured">featured</option>
</select>
<caption>Total {{computedProducts.length}} Products</caption>
<div class ="productListing" v-for="(product, index) in computedProducts" :key="index">
<div class="singleProduct box effect1">
<h1>{{product.name}}</h1>
<h1></h1>{{product.color}}
{{product.featured}}
</div>
</div>
</div>
</div>
</template>
vuejs part :
<script>
// # is an alias to /src
export default {
name: 'home',
data() {
return {
status: [],
products: [
{name:'test1', color:'red', size:'XL',status:"featured"},
{name:'test2', color:'black', size:'L',status:"onSale"},
{name:'test3', color:'red', size:'L',status:"featured"},
],
}
},
computed: {
computedProducts: function () {
return this.products.filter((item) => {
return (this.status.length === 0 || this.status.includes(item.status))
})
}
}
}
</script>
css part :
<style lang="scss" scoped>
.productListing {
display: grid;
grid-template-columns: 1fr 1fr
}
.box {
background:#FFF;
margin:40px auto;
}
/*==================================================
* Effect 1
* ===============================================*/
.effect1{
-webkit-box-shadow: 0 10px 6px -6px #777;
-moz-box-shadow: 0 10px 6px -6px #777;
box-shadow: 0 10px 6px -6px #777;
}
$green: #2ecc71;
$red: #e74c3c;
$blue: #3498db;
$yellow: #f1c40f;
$purple: #8e44ad;
$turquoise: #1abc9c;
.select {
border: 0.1em solid #FFFFFF;
margin: 0 0.3em 0.3em 0;
border-radius: 0.12em;
box-sizing: border-box;
text-decoration:none;
font-family:'Roboto',sans-serif;
}
</style>
thank you in advance for your help
You grid effect would appear under it children instead of itself.
You need to add one parent div for your products, like below
<div class="productListing">
<div v-for="(product, index) in computedProducts" :key="index">
......
</div>
</div>
CSS would be
.productListing {
display: grid;
grid-template-columns: repeat(3, 1fr);
}