how to fix unloaded images in "vue product zoomer" nuxt ssr - vue.js

i successfully implemented vue-product-zoomer in my nuxt ssr.
when i come to this page through $router everything works fine
but when i refresh page something went wrong
here is screenshot
i have code like this
<client-only>
<ProductZoomer
:base-images="images"
:base-zoomer-options="zoomerOptions"
/>
</client-only>
and scripts
zoomerOptions: {
zoomFactor: 4, // scale for zoomer
pane: 'pane',
hoverDelay: 300,
namespace: 'zoomer',
move_by_click: false,
scroll_items: 5,
choosed_thumb_border_color: 'orange',
scroller_button_style: 'line',
scroller_position: 'left',
zoomer_pane_position: 'right',
},

It happens sometimes and the only way that i found is to refresh the component, so do the following:
add key to your component
<client-only>
<ProductZoomer :base-images="images" :base-zoomer-options="zoomerOptions" :key=""key/>
</client-only>
on mounted hook increment the key
export default {
data(){
return{
key:0,
}
},
mounted(){
// You may need to do the increment in a setTimeout (as for me doing it after 2 sec because of my skeleton loader)
this.key++
}
}
Hope it works.

Related

CSS selector in Swiper js breaks

I have my swiper component:
<swiper [config]="slideOpts">
<ng-template swiperSlide *ngFor="let unit of Units" class="peeking-slide">
<fs-reserved-unit-card [router]="router" [activatedRoute]="activatedRoute" [doRefresh]="doRefresh" [Unit]='Unit' ></fs-reserved-unit-card>
</ng-template>
</swiper>
with slideOpts being:
slideOpts = {
slidesPerView: 'auto',
spaceBetween: 10
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
};
or:
slideOpts = {
slidesPerView: 'auto',
spaceBetween: 10
pagination: {
el: '.swiper-pagination',
type: 'bullets',
},
};
it seems that as soon as I seem to target the CSS selector it breaks, with the pagination if I have "el: x" the pagination bullets simply do not display. With the Navigation "theprevEl: x" and "nextEl: x" also does not display.
is there anything Im missing perhaps?
I believe you don't need to pass any css selectors at all as it is swiper angular component not vanilla js as far as i understand based on your code. It creates all elements and attaches all handlers itself.
Basically when you create pagination you just need to pass true or configuration and it works immediately - pagination renders without you providing classes.
Here is an example https://codesandbox.io/s/great-robinson-meeogx

Cannot make VueMapbox 100% of parent

I am using a VueMapbox with markers and trying to display it in a parent container. I added this CSS because without this the map has 0 height and width:
.mapboxgl-map {
position: relative !important;
}
I want the width to be 100% of the parent, so I added this which DOES work:
.mapboxgl-canvas {
height: 100% !important;
width: 100% !important;
}
HOWEVER, when you drag the map or zoom in, the markers move around as if the map is the default size. I've tried messing around with the CSS and I haven't had any success.
I've also tried calling map.resize() after the map gets loaded. The function gets called but doesn't do anything and once you zoom in to the map, the background disappears. Here is my component:
<template>
<MglMap :accessToken="accessToken" :mapStyle="mapStyle"
:center="coordinates"
#load="onMapLoaded"
>
<MglMarker v-for="team in teams"
:key="team.id"
:coordinates="[team.lng, team.lat]"
>
</MglMarker>
</MglMap>
</template>
<script>
import Mapbox from "mapbox-gl";
import { MglMap, MglGeojsonLayer, MglMarker, MglPopup } from "vue-mapbox";
export default {
components: {
MglMap,
MglGeojsonLayer,
MglMarker,
MglPopup
},
mixins: [teamHelper],
data() {
return {
accessToken: ...,
mapStyle: "mapbox://styles/mapbox/streets-v11",
coordinates: [-50.549668, 39.014],
map: null,
mapbox: null
}
},
props: {
teams: []
},
created() {
this.mapbox = Mapbox
},
methods: {
onMapLoaded(event) {
this.map = event.map;
this.map.resize(); // does not work
},
}
};
</script>
Once you resize the window it works as expected, so if there were a way to trigger that properly, then I feel like it should work. I've also read all of the similar questions on this I could find, and none helped, AND I read the documentation which does not mention anything about this.
I'm using Vue ^2.5.17 and vue-mapbox ^0.4.1
Alright well I found a somewhat hacky workaround. You just have to render the map component inside an IFrame, set the size of the IFrame to 100% of the parent and you're good to go.
If you need to pass data from the parent component to the child, you can do something like this: http://blog.pixelastic.com/2017/09/12/sending-data-to-an-iframe-with-vue-js/
If you have a better solution or know why the resizing wasn't working then please respond.

Vue JS props is underfined

Im using Gridsome frame work for VUE JS
I am navigating to a new page by using this.$router.push(PATH, PARAMS)
this.$router.push({path: `/${value.sectionLink}/`, params: {pageOBJ: value}})
The page route works fine - however the PROP, pageOBJ is undefined in the page as seen in the VUE inspector:
it should be an object (which is what VALUE is set to) i.e.
I've tried a number of different techniques to resolve this but have not managed to figure this out so I assume I have missed something here?
gridsome auto generates the page routes when you add a new PAGE.VUE file to the /pages folder -
Is this the issue?
Gridsome also references graphQI, are you supposed to grab the data using graph and not by pushing Props?
Any help would be amazing here - please let me know if you need any further information.
Thanks -
W
UPDATE BASED ON CURRENT ANSWERS:
I have already added props:true to the component as shown below, but the issue is still present.
CODE SNIPPET - SUMMARY:
User clicks on the SectionTitle component, this then emits the page link
(each of the SectionTitle is a object from : sections array of Object)
To see the current online version of this please look at
wtwd.ninjashotgunbear.com
<template>
<Layout>
<div class="navs" v-for="section in sections" :key="section.sectionTitle">
<!-- On click delay for screen to come ove top -->
<!-- router to be put here -->
<SectionTitle :data="section" #routeChange="reRoute($event)"/>
</div>
<PageTransition :dataObj="transitionObj"/>
</Layout>
</template>
<script>
import SectionTitle from '#/components/SectionTitle.vue';
import PageTransition from '#/components/PageTransition.vue'
export default {
metaInfo: {
title: 'Hello, world!'
},
components: {
SectionTitle,
PageTransition
},
data(){
return {
// data to be passed to the components
sections: [
{
sectionTitle: 'Clients',
sectionLink: 'clients',
sectionSubTitle: '"Some of the amazing humans I have had the pleasure of working with"',
backgroundColor: '#F08080',
titleColor: '#E65454'
},
{
sectionTitle: 'Projects',
sectionLink: 'projects',
sectionSubTitle: '"I LIKE TO MAKE PROJECTS THAT WILL TEST MY KNOWEDGE AND EXPOSE MY WEAKNESSES"',
backgroundColor: '#20B2AA',
titleColor: '#11DACF'
},
{
sectionTitle: 'Skills',
sectionLink: 'skills',
sectionSubTitle: `"LEARNING WILL NEVER END, SO LONG AS YOUR AMBITIONS ARE STOKED, AND I've got plenty of ambition"`,
backgroundColor: '#A921B2',
titleColor: '#CA14D6'
},
{
sectionTitle: 'About Me',
sectionLink: 'aboutme',
sectionSubTitle: `"My joruney becoming a developer so far"`,
backgroundColor: '#FFFFFF',
titleColor: '#D1D1D1'
},
{
sectionTitle: 'Contact Me',
sectionLink: 'contactme',
sectionSubTitle: `"If you have any questions or want to reach out about a project then i'd love to speak with you"`,
backgroundColor: '#2185B2',
titleColor: '#0076AB'
}
],
divText: null,
transitionObj: null
}
},
methods:{
reRoute(value){
// 1)A) - change the text of the div to say the section it is being moved to
this.divText = value.sectionTitle
this.transitionObj = value
// FIND center pixcle value to place text - scrolled height + windowHeight / 2 = centerPos
let centerPos = window.scrollY+(window.innerHeight/2)
// Apply secific Title color - and center possitioning
document.querySelector('.leaveScreen p').style.cssText=`color: ${value.titleColor}; top: ${centerPos}px`
// 1) animate the loading screen
let screen = document.querySelector('.leaveScreen');
screen.style.cssText=`background: ${value.backgroundColor}; left: 0%`;
// 2) re-route the page
setTimeout(()=>{
this.$router.push({path: `/${value.sectionLink}/`, params: {pageOBJ: value}}) // << says that the route name is not found
// this.$router.push(value.sectionLink)
}, 700)
}
}
}
</script>
<style lang="scss">
// **** ERROR CAUSED BY NOT INSTALLING SCSS package ****
// https://gridsome.org/docs/assets-css/ &&&& npm install -D sass-loader node-sass
// Universal Font being used - LEMON MILK
#font-face {
font-family: LemonMilk;
src: url('../assets/fonts/LemonMilk.otf');
}
* {
box-sizing: border-box;
}
.navs {
font-family: LemonMilk;
}
.SectionTitle{
cursor: pointer;
}
</style>
Pass name rather than path in this.$router.push()
this.$router.push({name: ${value.sectionLink}, params: {pageOBJ: value}})
You should add props:true to the route definition :
{
path:'/thepath/:theParam',
component:SomeComponent,
props:true
}

Disable ripple effect on vuetify components globally

I'm using vuetify on my application. The design team create a flat design and I want to change the theme of vuetify to match with mockups
I try to find an option to disable ripple effect easily all over the application but it doesn't exist.
I try to create a component extension to avoid repeating :ripple="false"on each component I use.
I'll take a button component as an example.
<v-btn :ripple="false">My Button</v-btn>
each button on my application need to have ripple=false
My aim is to create a component like this
<my-button>My Button</my-button>
I try to extend v-btn in another component like this.
<template>
<v-btn v-bind="options" :ripple="false"></v-btn>
</template>
<script>
import { VBtn } from 'vuetify';
export default {
name: 'MyButton',
extend: VBtn,
computed: {
options() {
return this.props;
},
},
};
</script>
<style scoped>
I try this way to avoid copy/paste all the props of v-btn.
All solutions that I've tried failed.
You can modify Vue.js components globally even after they've been registered.
In this case, you can simply do this :
const VBtn = Vue.component('VBtn')
VBtn.options.props.ripple.default = false
You can add that in your vuetify.js file before the export default new Vuetify (...) for instance.
- Tested with Vuetify 2.1.14
You can set the complete container to not visible.
.v-ripple__container {
display:none !important;
}
According to Vuetify documentation you can modify the Stylus variables - so you can try to redefine these to your taste, e.g. by setting them to none:
$ripple-animation-transition-in := transform .25s $transition.fast-out-slow-in, opacity .1s $transition.fast-out-slow-in
$ripple-animation-transition-out := opacity .3s $transition.fast-out-slow-in
$ripple-animation-visible-opacity := .15
Override ripple directive with global mixin in main.js
let overrideRipple = {
directives:{
ripple:{
inserted: ()=> {
console.log("Ripple overrided")
}
}
}
}
Vue.mixin(overrideRipple);
With the release of Vuetify 2.0 you can actually just turn off ripples globally by modifying your vuetify.js file like so.
export default new Vuetify({
global: {
ripples: false
},
icons: {
iconfont: 'mdi',
},
});

How to use use cytoscape.js in combination with vue.js dynamic component's keep-alive?

I am trying to build a single page application using Vue.js 2.0. The application is supposed to feature multiple modes of operation, which I wanted to implement using Vue.js dynamic component. Since the state of each mode should be preserved while switching between them, I decided to use the keep-alive feature that Vue.js provides. One of the modes is supposed to be a network view created by using Cytoscape.js .
And here comes my problem. The network is initialized correctly when I switch the first time to it, but after switching back and forth, the network view freezes. keep-alive works properly (as far as I understand it) and brings back both the Cytoscape instance and the proper HTML section. Somehow, the connection between the Cytoscape instance and the HTML sections seems to be lost, although I don't understand how and why.
Here is an example code.
//sample data for network
var testElements = [
{ data: {id: 'a'} },
{ data: {id: 'b'} },
{ data: {
id: 'ab',
source: 'a',
target: 'b'
}
}
];
//Vue components
Vue.component('otherView', {
template: '<div>This is another mode</div>'
});
Vue.component('network', {
template: '<div id="container" class="cy"></div>',
mounted: function () {
cy1 = cytoscape({
container: document.getElementById("container"),
elements: testElements
});
}
});
//Vue dynamic component
var vm = new Vue({
el: "#dynamic",
data: {
currentView: 'otherView'
}
});
.cy {
width: 500px;
height: 500px;
position: absolute;
top: 100px;
left: 10px;
}
<script src="https://rawgit.com/cytoscape/cytoscape.js/master/dist/cytoscape.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="dynamic" >
<div id="selectorButton">
<button id="button1" #click="currentView='otherView'">Other view</button>
<button id="button2" #click="currentView='network'">Network</button>
</div>
<keep-alive>
<component :is="currentView"></component>
</keep-alive>
</div>
If you remove a Cytoscape instance, you've destroyed it. Either make sure that Vue doesn't destroy your DOM elements or create a new Cytoscape instance each time from JSON: http://js.cytoscape.org/#cy.json
I could not understand your problem completely , but you can try shifting code you have written in network component's mounted oroperty to activated property as follows
Vue.component('network', {
template: '<div id="container" class="cy"></div>',
activated: function () {
if(initial state){
cy1 = cytoscape({
container: document.getElementById("container"),
elements: testElements
});
}
}
});
This may help because when a cmponent is kept-alive the mounted hook is called only once when first time enter you the component, its not called again on subsequent entering whereas activated hook is called everytime you enter the component when kept-alive