Nuxt application throwing error message when using Flickity - vue.js

I am trying to implement a carousel in a Nuxt application. This is my package.json
"dependencies": {
"#nuxtjs/i18n": "^7.0.3",
"core-js": "^3.15.1",
"flickity": "^2.2.2",
"lodash": "^4.17.21",
"nuxt": "^2.15.7",
"postcss-nesting": "^8.0.1",
"throttle-debounce": "^3.0.1",
"vue-flickity": "^1.2.1"
},
This is my code
<template>
<ClientOnly>
<Flickity
ref="flickity"
:key="keyIncrementer"
class="carousel"
:class="{ 'carousel--active': active }"
:options="computedOptions"
>
<slot />
</Flickity>
</ClientOnly>
</template>
<script>
import Flickity from 'vue-flickity'
const DEFAULT_OPTIONS = {
cellAlign: 'left',
pageDots: true,
prevNextButtons: true
}
export default {
components: {
Flickity,
},
name: 'BaseCarousel',
props: {
active: {
type: Boolean,
default: true
},
options: {
type: Object,
required: false,
default: () => ({})
}
},
If I don't comment out import Flickity from 'vue-flickity' and
components: { Flickity, }, I get this error message.
I can't understand what is wrong here. If someone knows please help...

Another workaround is to locally register vue-flickity as an async component only on the client:
export default {
components: {
[process.browser && 'Flickity']: () => import('vue-flickity'),
}
}
demo

Importing it as a plugin is a solution as shown here: https://github.com/drewjbartlett/vue-flickity/issues/38#issuecomment-906280271
Meanwhile, it is not optimal at all.
Importing it with a dynamic import may be a solution, I'm trying to find a way to write it properly.
Updated answer
This seems to work properly on my side, can you please confirm?
<template>
<ClientOnly>
<Flickity
ref="flickity"
:key="keyIncrementer"
class="carousel"
:class="{ 'carousel--active': active }"
:options="computedOptions"
>
<slot />
</Flickity>
</ClientOnly>
</template>
<script>
import Vue from 'vue'
const DEFAULT_OPTIONS = {
cellAlign: 'left',
pageDots: true,
prevNextButtons: true,
}
export default {
name: 'BaseCarousel',
props: {
active: {
type: Boolean,
default: true,
},
options: {
type: Object,
required: false,
default: () => ({}),
},
},
async mounted() {
if (process.browser) {
const Flickity = await import('vue-flickity')
Vue.component('Flickity', Flickity)
}
},
}
</script>

Have you added to the plugins/vue-flickity.js something like:
import Vue from 'vue'
import Flickity from 'vue-flickity'
Vue.component('Flickity', Flickity)
?
Add also to the nuxt.config.js
plugins: [
{ src: '~/plugins/vue-flickity.js', ssr: false },
]

Related

How to display local images from local json file in vue?

So I have a json file with this structure:
[
{
"id": 1,
"name": "name1",
"img": "pic1.jpg"
}
]
I am making a vue project where after I import it I'm trying to use as the img name in src for my image:
<div v-for="item in countries" :key="item.id">
<img :src="../src/assets/images/`item.img`" alt="">
</div>
But image doesn't appear, rest of the data is fine. How do I get the image?
Home.vue script
<script>
import { useDark, useToggle } from '#vueuse/core'
import jsonData from "../data/country.json"
export default {
name: "Home",
setup() {
const isDark = useDark();
const toggleDark = useToggle(isDark);
console.log(isDark.value);
return {
isDark,
toggleDark
}
},
data: function () {
return {
isSideOpen: false,
drawer: true,
isTheme: false,
listView: false,
show: false,
}
},
data() {
return {
countries: jsonData
}
},
}
</script>
Vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '#vitejs/plugin-vue'
export default defineConfig({
plugins: [
vue(),
laravel({
input: [ 'resources/js/app.js'], //worls best without css
refresh: true,
}),
],
});

how to create vue-shepperd component

I am trying to develop guided tour with shepherd: https://www.npmjs.com/package/vue-shepherd but I cannot get the element. So here is my component for guide tour:
<template>
<div></div>
</template>
<script>
import { useShepherd } from 'vue-shepherd';
export default {
props: {
element: {
required: true,
},
id: {
type: Number,
required: true,
},
title: {
type: String,
},
text: {
type: String,
required: true,
},
position: {
type: String,
required: true,
},
},
mounted() {
this.tour.start();
},
data() {
return {
tour: null,
};
},
methods: {
createTour() {
this.tour = useShepherd({
useModalOverlay: true,
});
this.tour.addStep({
title: this.title,
text: this.text,
attachTo: { element: this.element, on: this.position },
buttons: [
{
action() {
return this.back();
},
classes: 'shepherd-button-secondary',
text: 'Back',
},
{
action() {
return this.next();
},
text: 'Next',
},
],
id: this.id,
});
this.tour.start();
},
},
created() {
this.createTour();
},
};
</script>
and here is my parent component:
<button ref="button">
Click
</button>
<guide :element="element" :title="'Tour'" :text="'Example'" :position="'bottom'" :id="1" />
and the mounted of the parent element:
mounted() {
this.element = this.$refs.button;
},
but the tour doesnt attach the the button element. it just appears in the middle of the page. Why do you think it is?
Looks like a usage problem in vue hooks. The child component's hooks fire before the parent component's hooks. Therefore, at the time of the creation of the tour, the element does not exist. Vue-shepherd does not use vue reactivity.
Use
mounted() {
this.$nextTick(() => {
this.createTour();
});
},
Codesanbox
But it's better to change the component structure. If you are using vue3 you can use my package
In this case it will look like this
<template>
<button v-tour-step:1="step1">
Click
</button>
</template>
<script>
import { defineComponent, inject, onMounted } from "vue";
export default defineComponent({
setup() {
const tour = inject("myTour");
onMounted(() => {
tour.start();
});
const step1 = {
/* your step options */
}
return {
step1,
};
}
});
</script>

How to change tooltip background color vue-chartjs?

I've added tooltips.backgroundColor in chartOptions but still doesn't work, so anyone can help me?
Here is my code
<template>
<Doughnut
:chart-options="chartOptions"
:chart-data="chartData"
:chart-id="'doughnut-chart'"
:styles="styles"
:width="width"
:height="height"
/>
</template>
<script lang="ts">
import { defineComponent, type PropType } from "vue";
import TypographyComponent from "#/core/ui/components/typography/Typography.component.vue";
import { Doughnut } from "vue-chartjs";
import {
Chart as ChartJS,
Title,
Tooltip,
Legend,
ArcElement,
CategoryScale,
type Plugin,
} from "chart.js";
ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale);
export default defineComponent({
name: "ProgressChartComponent",
components: { Doughnut, TypographyComponent },
props: {
width: {
type: Number,
default: 400,
},
height: {
type: Number,
default: 400,
},
styles: {
type: Object as PropType<Partial<CSSStyleDeclaration>>,
default: () => {},
},
chartData: {
type: Object,
required: false,
default: () => {},
},
},
setup() {
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
cutout: "64%",
tooltips: {
enabled: false,
backgroundColor: "#227799",
},
};
return {
chartOptions,
};
},
});
</script>
...
Guessing that you're using Chart.js v3, be aware that the tooltips are defined in the namespace options.plugins.tooltip but not options.tooltips as in your code. Therefore chartOptions needs to be changed as follows:
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
cutout: "64%",
plugins: {
tooltip: {
backgroundColor: "#227799"
}
}
};
For further information, please consult Tooltip Configuration from the Chart.js documentation.

ag-Grid does not support .vue component as cellRenderer?

So I have this itemlist.vue file
<div>
<div>
<ag-table
style=" height: 650px;"
class="ag-theme-balham"
:column-defs="columnDefs"
:row-data="rowData"
/>
</div>
</div>
</template>
<script>
import AgTable from "../components/AgTable";
import editRenderer from "../components/AgGridRenderers/editDeleteRenderer.vue";
export default {
components: {
AgTable
},
data: () => ({
users: [],
columnDefs: null,
rowData: null,
editR: editRenderer
}),
mounted () {
this.columnDefs = [
{ headerName: "Name", field: "name", sortable: true, filter: true },
{ headerName: "e-Mail", field: "email", sortable: true, filter: true },
{ headerName: "Contact", field: "contact", sortable: true, filter: true },
{ headerName: "Contact", field: "contact", sortable: true, filter: true, cellRenderer: editRenderer }
];
this.rowData = [
{ name: "Robin Sharma", email: "robin#sharma.com", contact: 8508035076 },
{ name: "Amish Tripathi", email: "amish#tripathi.com", contact: 9250035054 },
{ name: "Zig Ziglar", email: "zig#ziglar.com", contact: 9206635030 },
{ name: "Paulo Coelho", email: "paolo#coelho.com", contact: 7288012335 }
];
},
methods: {
loadUsers () {
// console.log("Loading Users from api.");
}
}
};
</script>
And index.vue file for Ag grid table as
<template>
<div>
<ag-grid-vue
style=" height: 650px;"
class="ag-theme-balham"
:column-defs="_props.columnDefs"
:row-data="_props.rowData"
:framework-components="frameworkComponents"
/>
</div>
</template>
<script>
import "ag-grid-community/dist/styles/ag-grid.css";
import "ag-grid-community/dist/styles/ag-theme-balham.css";
import { AgGridVue } from "ag-grid-vue";
import editRenderer from "../AgGridRenderers/editDeleteRenderer.vue";
export default {
components: {
AgGridVue
},
props: [
"column-defs", "row-data"
],
data: () => ({
frameworkComponents: {
editRenderer
}
}),
mounted () {
console.log(this._props.columnDefs, this._props.rowData);
}
};
</script>
And editrenderer.vue file as:
<template>
<div>
<span>
<button #click="sayHi"> Edit Item </button>
</span>
</div>
</template>
<script>
export default {
created () {
console.log("Hello from Edit");
},
methods: {
sayHi () {
alert("Hi");
}
}
};
</script>
And all I am getting in the DOM is empty edit-renderer tags
Doesn't AgGrid support cellRenderers in Vue Js?
In the end the imported component appears as a vue component in the Dom if used separately as a common Dom element. Does that mean we explicitly have to compile it somehow? I also tried using setTimeOut before initializing columnDefs and rowData where AgTable is used. but still it doesn't show anything in the table.
Ok, so what I did was add some missing properties to ag-grid-vue element such as grid-options, context and grid-ready, and add refresh function to the renderer component, and convert all related components from simple "export default{" to "export default Vue.extends({".
I think this problem was resolved.
Though, I am getting 'this is undefined' error now.
Ag-grid should clarify which parameters are compulsory other than rowData and colDefs with their purpose.

Vue Cannot read property '$refs' of undefined

I have a Vue application that leverages Vuetify. In this application I have a component called city-selector.vue which is setup like this:
<template>
<select-comp
:id="id"
:items="cityList"
:item-text="name"
:item-value="cityCode"
#input="onInput">
</select-comp>
</template>
<script>
import VSelect from '../vuetify/VSelect';
export default {
name: 'city-select-comp',
extends: VSelect,
props: {
id: {
type: String,
default: '',
},
cityList: {
type: Array,
default: () => { return [] }
},
},
methods: {
onInput() {
//Nothing special, just $emit'ing the event to the parent
},
},
}
</script>
Everything with this component works fine except that when I open my dev tools I get a bunch of console errors all saying this (or something similar to this):
Cannot read property '$refs' of undefined
How can I fix this sea of red?
This is due to a bad import that you do not need. Remove the import VSelect and the extends statements and your console errors will disappear, like this:
<script>
export default {
name: 'city-select-comp',
props: {
id: {
type: String,
default: '',
},
cityList: {
type: Array,
default: () => { return [] }
},
},
methods: {
onInput() {
//Nothing special, just $emit'ing the event to the parent
},
},
}
</script>