I use Primevue V3 to make doughnuts charts but i don't know how to display something in arc of doughnuts charts. I have found the plugins chartjs-plugin-labels to display something but i don't know how to use it with PrimeVue.
My Vue file
<template>
<div>
<Chart ref="primeChart" type="doughnut" :data="chartData" :options="lightOptions" />
</div>
</template>
<script setup >
import {ref} from "vue";
const chartData = ref({
labels: ['A', 'B', 'C'],
datasets: [
{
data: [300, 50, 100],
backgroundColor: ["#FF6384", "#36A2EB", "#FFCE56"],
hoverBackgroundColor: ["#FF6384", "#36A2EB", "#FFCE56"]
}
]
});
const lightOptions = ref({
plugins: {
legend: {
display: true
}
}
});
</script>
Thanks for your help :)
chartjs-plugin-labels is for legacy versions of Chart.js. Use chartjs-plugin-datalabels for Chart.js 3 or newer.
The PrimeVue Chart component has a plugins property that receives an array of Chart.js plugins to use:
<script setup>
import ChartDataLabels from 'chartjs-plugin-datalabels'
const plugins = [ChartDataLabels]
⋮
</script>
<template>
<Chart :plugins="plugins" ⋯ />
</template>
demo
Related
I create a component whose purpose is to display an arbitrary component within itself, with a changeable padding property. (The example is conditional for simplicity).
<script setup lang="ts">
defineProps<{
innerComponent: any;
settings: { padding: number; backgroundColor: string };
}>();
</script>
<template>
<div
:style="`
padding: ${settings.padding}px;
background-color: ${settings.backgroundColor}`"
>
<component :is="innerComponent" />
</div>
</template>
Let's create a simple component for the example.
<template>
<p style="background-color: beige">it's just a test.</p>
</template>
That's how we use it, and it works great.
<script setup lang="ts">
import ExternalComponent from "./components/ExternalComponent.vue";
import InnerComponent from "./components/InnerComponent.vue";
</script>
<template>
<ExternalComponent
:inner-component="InnerComponent"
:settings="{ padding: 200, backgroundColor: 'yellow' }"
/>
</template>
I wish it all looked even more aesthetically pleasing. For example, like this.
<InnerComponent v-inner="{ padding: 200, backgroundColor: 'yellow' }" />
Let's try using custom directives.
import { createApp, h } from "vue";
import App from "./App.vue";
const app = createApp(App);
app.directive("inner", (el, binding, vnode) => {
//Here is supposedly expected to be something like
el.outerHTML = h("ExternalComponent", {
innerComponent: vnode,
settings: binding.value,
});
//or
vnode = h("ExternalComponent", {
innerComponent: vnode,
settings: binding.value,
});
//But, of course, something completely different :((
});
app.mount("#app");
Unfortunately, my knowledge is not enough to solve this problem. I would be glad to get any advice on what direction to dig.
First I tried this as showed in official Swiper.js website for Vue 3 demo
<template>
<swiper
:effect="'coverflow'"
:grabCursor="true"
:centeredSlides="true"
:slidesPerView="'auto'"
:coverflowEffect="{
rotate: 50,
stretch: 0,
depth: 100,
modifier: 1,
slideShadows: true,
}"
:pagination="true"
:modules="modules"
class="mySwiper"
>
<swiper-slide v-for="card in cards"
><img
:src="card.image" /></swiper-slide>
</swiper>
</template>
<script>
// Import Swiper Vue.js components
import { Swiper, SwiperSlide } from "swiper/vue";
// Import Swiper styles
import "swiper/css";
import "swiper/css/effect-coverflow";
import "swiper/css/pagination";
import "./style.css";
// import required modules
import { EffectCoverflow, Pagination } from "swiper";
export default {
props: ['cards']
setup() {
return {
modules: [EffectCoverflow, Pagination],
};
},
};
</script>
And it did not work.
Then I tried to import it as a plugin in plugins folder of nuxt:
import Vue from 'vue';
import { Swiper, EffectCoverflow, Pagination } from "swiper";
const swiper = {
install(Vue, options) {
Vue.prototype.$swiper = Swiper;
Vue.prototype.$swiperModules = {
EffectCoverflow,
Pagination,
};
}
};
Vue.use(swiper);
And registred it in nuxt.js.config as: src: './plugins/swiper.client.js', mode: 'client'
And tried to use it in my component like this:
<template>
<Swiper>
<SwiperSlide v-for="card in cards" :key="card.id">
<NuxtLink :to="`products/${card.id}`" class="card">
<img
:src="require(card.image)"
alt="image"
class="image"
/>
<h3 class="header">{{ card.title }}</h3>
<p class="snippet">{{ card.snippet }}</p>
</NuxtLink>
</SwiperSlide>
</Swiper>
</template>
<script>
export default {
props: ['cards'],
mounted() {
this.swiper = new this.$swiper('.swiper', {
loop: true,
// configure Swiper to use modules
modules: [
this.$swiperModules.Pagination,
this.$swiperModules.EffectCoverflow,
],
})
},
}
</script>
And it is still not working, What am I doing wrong?
Can anyone help with it?
TLDR: Nuxt2 and Swiper8 are not compatible.
Swiper v8.0.0 is almost 1 year old: https://github.com/nolimits4web/swiper/releases/tag/v8.0.0
2 years ago, nolimits4web aka the main maintainer of the package said
Swiper Vue.js components are compatible only with new Vue.js version 3
Easy to say that the v8 of Swiper is definitely not compatible with Nuxt2 (using Vue2).
Even if there was a hack, it would be quite dirty and not the thing that I would recommend overall.
swiper#8.4.5 is also 38.7kB gzipped, which is quite on the heavy side of things.
If you're using all of its features and ready to upgrade to Nuxt3 (which might not be trivial), then you could maybe proceed.
Otherwise, you could maybe design your own carousel component or check the ones available here: https://github.com/vuejs/awesome-vue#carousel
I'm guessing that there are some projects with Nuxt2 support still, not too heavy and still maintained that could satisfy your needs.
I'm trying to import SVG icons for each item in a v-for loop, with the filename changing depending on the item's id. The icons are loading, but I get the following error for each icon imported.
Is there a better way to approach this?
Uncaught (in promise) TypeError: Failed to resolve module specifier '~/assets/img/flags/ar.svg'
<template>
<NavigationItem v-for="item in topCountries">
<template #icon>
<component :is="getIcon(item.id)" />
</template>
<NavigationItem />
</template>
<script setup>
const getIcon = (id) => defineAsyncComponent(() =>
import(`~/assets/img/flags/${id}.svg`));
</script>
You can have a look at https://nuxt.com/modules/nuxt-svgo module.
This module allows to import SVG.
npm i --save nuxt-svgo
Add it as a module dependency in your nuxt.config file
// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
modules: ['nuxt-svgo']
})
Import SVG icons as follow:
<script setup lang="ts">
const getIcon = (id: string) => defineAsyncComponent(() => import(`#/assets/svg/${id}.svg`));
</script>
<template>
<div v-for="item in ['icon1', 'icon2']">
<component :is="getIcon(item)" />
</div>
</template>
Note that if you use Typescript, you will have to create a custom.d.ts file to fix import error
// custom.d.ts
declare module '*.svg' {
import type { DefineComponent } from 'vue'
const component: DefineComponent
export default component
}
calls each icon from the data. uses font awesome icons. you can also add svgs between the i tags
<template>
<ul>
<!-- list rendering -->
<li v-for="item in items">
<span class="icon">
<i :class="[faClass(item.icon)]"
aria-hidden="true"></i>
</span>
</li>
</ul>
</template>
<script>
export default {
name: "navbarMobile",
data() {
return {
//listItems
items: [
{
icon: 'home',
},
{
icon: 'wrench',
},
{
icon: 'project-diagram',
},
{
icon: 'cogs',
},
{
icon: 'phone',
}
]
}
},
methods: {
faClass(icon) {
return `fa fa-${icon}`;
}
}
}
</script>
Us the component name instead of the component path. Also, don't forget to import SVG components and add ?inline at the end of the name.
<template>
<NavigationItem v-for="item in topCountries">
<template #icon>
<component :is="item.icon" />
</template>
<NavigationItem />
</template>
<script setup>
import Eye from '~/assets/img/flags/Eye.svg?inline';
import Balls from '~/assets/img/flags/Balls.svg?inline';
const topCountries = [
{ icon: 'Eye' },
{ icon: 'Balls' }
]
</script>
I am creating simple app using Vue3, also I am using Swiprer.js for vue, documentation of swiper.js (for vue3) is incomprehensible to me, I have imported all modules in my application, but now i want to create vertical scrollable slider, like picture below, my swiper component looks like this:
but still can't create vertical scrollable slider, this what my template looks like, any solutions?
<template>
<div class="container-main-slider">
<div class="container-main-slider__inner" id="sliderBox">
<swiper
:slides-per-view="1"
:space-between="20"
:direction="vertical"
:pagination="{ clickable: true}"
>
<swiper-slide>
<img :src="dynamic content">
</swiper-slide>
</swiper>
</div>
</div>
</template>
<script>
/* swiper slider imports */
import { Swiper, SwiperSlide } from "swiper/vue";
import SwiperCore, { A11y, Autoplay, Pagination } from "swiper";
import "swiper/swiper.scss";
import "swiper/swiper.scss";
import 'swiper/components/pagination/pagination.scss';
SwiperCore.use([A11y, Autoplay,Pagination]);
export default {
data(){
return{
fixedheader:false,
}
},
components: {
Swiper,
SwiperSlide,
},
methods:{
showVideo(){
this.$store.commit("CheckvideoVisibility", false)
},
onSlideChange() {
console.log('slide change');
},
},
};
</script>
`
I have a solution
If someone faced the same problem: you just need to put 'vertical' in single quotes.
It will look like this in Vue template:
<swiper
:slides-per-view="1"
:space-between="0"
:direction="'vertical'"
>
I'm trying to implement a simple world map in a Vue application. I have created a MapContainer component that is then imported into my main app. Below is the code for MapContainer.vue:
<template>
<div
ref="map-root"
style="width: 100%, height: 100%">
</div>
</template>
<script>
import View from 'ol/View';
import Map from 'ol/Map';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import 'ol/ol.css';
export default {
name: 'MapContainer',
components: {},
props: {},
mounted() {
new Map({
target: this.$refs['map-root'],
layers: [
new TileLayer({
source: new OSM()
})
],
view: new View({
zoom: 0,
center: [0, 0],
constrainResolution: true
})
});
}
}
</script>
<style>
</style>
I am registering the MapContainer component and then simply placing it inside a div in the parent component. When I import this component and try to use it, I get an empty div in place of the map. Does anyone know what I'm doing wrong?
Here is the parent component's code:
<template>
<div>
<map-container></map-container>
</div>
</template>
<script>
import MapContainer from '../mapping/MapContainter.vue';
export default {
components: {
'map-container': MapContainer
}
}
</script>
I fixed this by adding the following class to the div with the ref:
.map {
width: 100% !important;
height: 600px !important;
}
(The !important's might not be strictly necessary).