Whenever the v-carousel moves onto the next image in the reel it shrinks down before loading the image, causing the carousel to 'skip'. Is there any way to prevent this? Perhaps by pre-loading the images? The static images come from a parent nuxt component using asyncData so I thought it would already be loaded.
The carousel component:
<template>
<v-container class="hero-wrapper">
<v-carousel
cycle
hide-delimiters
height="auto"
>
<v-carousel-item
v-for="(item,i) in heroImages"
:key="i"
class="pb-0 mb-0"
:href="item.link"
>
<img :src="item.image" class="hero-image">
</v-carousel-item>
</v-carousel>
</v-container>
</template>
<script>
export default {
props: ["heroImages"]
}
</script>
Try adding the eager prop to v-carousel-item.
<v-carousel-item
v-for="(item,i) in heroImages"
:key="i"
eager
class="pb-0 mb-0"
:href="item.link"
>
Related
I cannot find one proper example of loading an image with a skeleton loader. I'm using nuxt + Vuetify and I'm trying to use a simple image with a skeleton loader.
Here is my code.
<template>
<v-skeleton-loader v-if="loading" :loading="loading" type="image">
<v-card
v-show="loaded"
class="ma-auto elevation-4"
shaped
color="darkgreen"
width="500"
flat
>
<v-img
src="/products/em-lucky-combo.jpg"
max-width="500"
#load="hasLoaded"
>
</v-img>
</v-card>
</v-skeleton-loader>
</template>
my method
<script>
export default {
methods: {
hasLoaded() {
console.log('Image finished loading')
this.loading = false
this.loaded = true
},
},
}
</script>
But as I said the method never gets called when it is inside the v-card tag or directly in the skeleton loader.
I have tried using #load, I have tried using mounted hooks like below.
<script>
export default {
mounted() {
const readyHandler = () => {
if (document.readyState === 'complete') {
console.log('Document Rendered')
this.loading = false
this.loaded = true
document.removeEventListener('readystatechange', readyHandler)
}
}
document.addEventListener('readystatechange', readyHandler)
readyHandler() // in case the component has been instantiated lately after loading
},
}
</script>
But nothing seems to work properly or elegantly. Is it just not possible? The moment the <v-img> tag is inside the skeleton loader or inside a v-card inside a skeleton loader it never gets rendered no matter what I do. One suggestion was to use a slot. I'm guessing it has something to do with slots but I do not understand how to use these.
I tried doing something like this.
<template v-slot:default>
<v-card
class="ma-auto elevation-4"
shaped
color="darkgreen"
width="500"
transition="fade-transition"
flat
>
<v-img
src="/products/em-lucky-combo.jpg"
max-width="500"
transition="fade-transition"
#load="imageLoaded"
></v-img>
</v-card>
</template>
I tried using the code below.
How to make v-skeleton loader inside v-for in Vuetify
<v-img>
<template #placeholder>
<v-sheet>
<v-skeleton-loader />
</v-sheet>
</template>
</v-img>
At the end, OP had enough of using just some dimensions and a lazy loader image. Since images were local, there was no need for a skeleton.
<template>
<v-card class="ma-auto elevation-4" flat shaped width="500">
<v-img
aspect-ratio="1"
class="grey lighten-2"
lazy-src=""
max-height="350"
max-width="500"
src="/"
transition="fade-transition"
>
<template v-slot:placeholder>
<v-row
align="center"
class="fill-height ma-0"
justify="center"
>
<v-progress-circular
color="grey lighten-5"
indeterminate
></v-progress-circular>
</v-row>
</template>
</v-img>
</v-card>
</template>
Thanks to #kissu I realised my approach was wrong and unnecessary . I ended up giving my images some set dimensions and using a lazy image loader with a placeholder slot which works just fine. As he mentioned my images are loaded locally so it wont really work in my case.
What I did in the end.
<template>
<v-card class="ma-auto elevation-4" flat shaped width="500">
<v-img
aspect-ratio="1"
class="grey lighten-2"
lazy-src=""
max-height="350"
max-width="500"
src="/"
transition="fade-transition"
>
<template v-slot:placeholder>
<v-row
align="center"
class="fill-height ma-0"
justify="center"
>
<v-progress-circular
color="grey lighten-5"
indeterminate
></v-progress-circular>
</v-row>
</template>
</v-img>
</v-card>
</template>
carousel component seems can only set height. i want do like this but it not work.
<v-responsive :aspect-ratio="16/9">
<v-carousel>
<v-carousel-item v-for="item in [url1,url2]" :key="item" :src="item">
</v-carousel-item>
</v-carousel>
</v-responsive>
I want to use autocomplete from Vuetify and I am facing issues there because on my website I have one of the outer divs position: relative the dropdown part of the autocompelete, which is position: absolute, is attaching itself not to the bottom of the input but in random place.
Autocomplete has a prop attach which Specifies which DOM element that this component should detach to. Use either a CSS selector string or an object reference to the element. so I thought I use that and set it to class of my input.
And this works but it causes warning in the console
[Vuetify] Unable to locate target v-autocomplete
found in
---> <VMenu>
<VAutocomplete>
<VCard>
<VApp>
<Root>
Here the link where I reproduced the console warning.
If you are not using v-app component in App.vue, make sure to add data-app attribute to the div with the id app in App.vue.
The result will be like the following:
<template>
<div id="app" data-app>
.... All components, routers, views here ...
</div>
</template>
This worked for me:
<div id="app">
<v-app id="inspire">
<v-card>
<v-card-title class="headline font-weight-regular blue-grey white--text">Profile</v-card-title>
<v-card-text>
<v-subheader class="pa-0">Where do you live?</v-subheader>
<v-autocomplete
v-model="model"
:hint="!isEditing ? 'Click the icon to edit' : 'Click the icon to save'"
:items="states"
:readonly="!isEditing"
:label="`State — ${isEditing ? 'Editable' : 'Readonly'}`"
persistent-hint
prepend-icon="mdi-city"
:attach="'#attach'"
>
<template v-slot:append-outer>
<div id="attach"></div>
<v-slide-x-reverse-transition
mode="out-in"
>
<v-icon
:key="`icon-${isEditing}`"
:color="isEditing ? 'success' : 'info'"
#click="isEditing = !isEditing"
v-text="isEditing ? 'mdi-check-outline' : 'mdi-circle-edit-outline'"
></v-icon>
</v-slide-x-reverse-transition>
</template>
</v-autocomplete>
</v-card-text>
</v-card>
</v-app>
</div>
pls, am trying to add some components dynamically in vue so that i can easily create some tabs, the components are all stored in an array, but when i looped through each of those components, it displayed the name of the components instead of the content of the components, below is my code
<template>
<v-card>
<v-tabs color="#4FC3F7" slider-color="#004D40" right grow>
<v-tab ripple v-for="(ttab, index) in tabss" :key="index">{{ttab}}</v-tab>
<v-tab-item v-for="(tabCont, index) in tabConts" :key="index">
{{tabCont}}
</v-tab-item>
</v-tabs>
</v-card>
</template>
<script>
import ProfileComponents from './Profile.vue'
import PasswordsComponents from './Passwords.vue'
import ProjectsComponents from './Projects.vue'
import FiniancialsComponents from './Finiancials.vue'
import VerificationsComponents from './Verifications.vue'
export default {
data() {
return {
tabss:['Profile','Passwords','Projects','Finiancials','Verifications'
],
tabConts:['<ProfileComponents/>','<PasswordsComponents/>','<ProjectsComponents/>','<FiniancialsComponents/>','<VerificationsComponents/>'
],
};
},
components:{
ProfileComponents, PasswordsComponents, ProjectsComponents, FiniancialsComponents, VerificationsComponents
}
}
</script>
pls what am i doing wrong
For starters, tabConts is just an array of strings, so you're getting what you are asking for.
You probably want to use the 'component' component, which lets you specify the name of the component to insert as a property:
<component v-bind:is="componentName"></component>
So your template changes to something like this:
<template>
<v-card>
<v-tabs color="#4FC3F7" slider-color="#004D40" right grow>
<v-tab ripple v-for="(ttab, index) in tabss" :key="index">{{ttab}}</v-tab>
<v-tab-item v-for="(tabCont, index) in tabConts" :key="index">
<component :is="tabCont"></component>
</v-tab-item>
</v-tabs>
</v-card>
</template>
This assumes the components are registering themselves correctly, etc., but this should get you closer to a solution.
I'm using bootstrap-vue package. In some component I have three card-flip components:
<b-row>
<b-col lg="4">
<card-flip :order="'fifth'"></card-flip>
</b-col>
<b-col lg="4">
<card-flip :order="'sixth'"></card-flip>
</b-col>
<b-col lg="4">
<card-flip :order="'seventh'"></card-flip>
</b-col>
</b-row>
and inside this card-flip component I'm displaying three different buttons depending on :order prop:
<template>
<!-- some not related content -->
<template v-if="order === 'fifth'">
<button class="card-flip__button card-flip__button--2"
v-b-modal.modalStandard="">
Sprawdź ofertę1
</button>
</template>
<template v-if="order === 'sixth'">
<button class="card-flip__button card-flip__button--2"
v-b-modal.modalPremium="">
Sprawdź ofertę2
</button>
</template>
<template v-if="order === 'seventh'">
<button class="card-flip__button card-flip__button--2"
v-b-modal.modalPremiumPlus="">
Sprawdź ofertę3
</button>
</template>
<modal-standard></modal-standard>
<modal-premium></modal-premium>
<modal-premium-plus></modal-premium-plus>
</template>
I'm using this template syntax to not create unnecessary divs.
And issue is that when I click some of this button it open correct modal but three times on top of previous ones.
I'm adding correct id's to <b-modal> inside those modal-* components.
This is done because each modal is rendered three times, one for each card-flip. You should also add v-if="order === 'fifth'" etc also for each modal in your card-flip template.