how to use vuechartkick in nuxt js - javascript

I create vuechartkick plugin in /plugin/vue-chartkick.
import Vue from 'vue'
import Chartkick from 'vue-chartkick'
import Chart from 'chart.js'
Vue.use(Chartkick.use(Chart))
nuxt template
<div class="pa-4 pa-md-8">
<div class="border-light pa-4 pa-md-12">
<line-chart legend="bottom" :data="series(resultSet)"> </line-chart>
</div>
</div>
Then I add the file path inside the plugins key of our nuxt.config.js.
plugins: [
'~/plugins/vue-chartkick.js',
],
I received this error
[Vue warn]: Unknown custom element: <line-chart> - did you register the component correctly? For recursive components, make sure to provide the "name" option
But not working correctly.

Some plugins might work only in the browser because they lack SSR support.
vue-chartkick and chart.js cannot be run on server side, therefore you have to enable your custom plugin only on client side as follows:
plugins: [
{ src: '~/plugins/vue-chartkick.js', mode: 'client' },
],
or by naming convention *.client.js:
plugins: [
'~/plugins/vue-chartkick.client.js',
],
See docs: https://nuxtjs.org/docs/2.x/directory-structure/plugins/#object-syntax
In addition, your component will be used to render a component only on client-side. So you have to use the <client-only> helper element in your Nuxt page as below:
<template>
<div>
<client-only placeholder="loading...">
<your-chart-component>
</client-only>
</div>
</template>
To know more, see nuxt docs: https://nuxtjs.org/docs/2.x/features/nuxt-components#the-client-only-component

Related

Client-only Nuxt 3 Vue plugin

I am new to Nuxt and Vue, so go easy on me. I am trying to create a video player component in my Nuxt 3 app using vue3-video-player, which doesn't seem to support SSR based on the following error I get when I import it in my video component:
ReferenceError: navigator is not defined
This error persists even if the component is wrapped with <ClientOnly>. So, based on what I saw in the Nuxt 3 Documentation I thought I would create a client-only plugin located at plugins/vue3-video-player.client.js with the following contents:
import Vue3VideoPlayer from '#cloudgeek/vue3-video-player'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(Vue3VideoPlayer)
})
But when I try to use it in my component as <vue3-video-player>, I get the following error:
[Vue warn]: Failed to resolve component: vue3-video-player
So I guess my question is how do I create a client-only Vue component using Nuxt 3 plugins? Or is there an entirely different approach that would work better?
Solution for nuxt 3:
Nuxt will automatically read the files in your plugins directory and load them. You can use .server or .client suffix in the file name to load a plugin only on the server or client side.
For example:
plugins/apexcharts.client.ts
Everything is so simple! And that is why we love nuxt ❤️
Solution for nuxt 2 (to show the difference):
nuxt.config.ts
plugins: [
{src: '~/plugins/apexcharts', mode: 'client'}
],
This is only for nuxt 2 because All plugins in your nuxt 3 plugins/ directory are auto-registered, so you should not add them to your nuxt.config separately.
you could try to provide a helper function. As mentioned in the docs.
import Vue3VideoPlayer from '#cloudgeek/vue3-video-player'
export default defineNuxtPlugin((nuxtApp) => {
return {
provide: {
Vue3VideoPlayer
}
}
})
To tag along with the given correct answer here,
If you're trying to install and use a third party NPM package, and running into "window is not defined" type errors, you can load the package as a plugin as follows (eg WAD)
npm install web-audio-daw
// plugins/wad.client.ts
import Wad from "web-audio-daw"
export default defineNuxtPlugin(nuxtApp => {
return {
provide: {
Wad,
}
}
})
// pages/whatever.vue
<script lang="ts" setup>
const { $Wad } = useNuxtApp();
// Can use $Wad normally from here on out
</script>

Rollup: VueJS composition api - Ref is not defined

I'm trying to use the composition api in a vue 2 module. When I initially created the npm module in the options api, I haven't experienced any issues and the module was installed and utilised accordingly. However, when I try to convert it to the composition api, I keep getting an error stating 'ref is not defined', after I install the npm module. From what I can understand, I must have something missing in the rollup config, but I can't really understand what as I'm fairly new to this.
Usually I would import ref in a component with the following code:
import {ref} from '#vue/composition-api';
For this case however, it doesn't cut it.
My rollup config file looks like this:
import commonjs from '#rollup/plugin-commonjs';
import vue from 'rollup-plugin-vue';
import buble from '#rollup/plugin-buble';
import scss from 'rollup-plugin-scss';
export default {
external: ['vue', '#vue/composition-api'],
input: 'src/index.js',
output: {
name: 'BasicDropdown',
exports: 'named',
format: 'cjs',
globals: {
vue: 'vue',
compositionApi: '#vue/composition-api',
}
},
plugins: [
scss(),
vue({
css: true,
compileTemplate: true,
scss: true,
preprocessStyles: true
}),
commonjs(),
buble(),
],
};
I also tried using #rollup/plugin-node-resolve, but this also didn't work.
Can someone kindly explain what I should do to import the ref functions from the vue composition api?
EDIT: The error message I'm getting is [Vue warn]: Error in data(): "ReferenceError: ref is not defined"

How to use vue-tel-input-vuetify in Nuxt?

I have been trying to use vue-tel-input-vuetify in Nuxt and I have been having the issue as it is in the image below, I have also tried all the solutions in this link Github but I get the same error.
After installation, I created a plugin file plugins/vue-tel-input-vuetify.js and added the following code to it.
import Vue from 'vue'
import VueTelInputVuetify from 'vue-tel-input-vuetify'
Vue.use(VueTelInputVuetify)
After that, I added this to nuxt.config.js
plugins: [
'~/plugins/vue-tel-input-vuetify',
{ src: '~/plugins/vue-google-charts', mode: 'client' }
]
Between my component's script tags, I did this:
import { VueTelInputVuetify } from 'vue-tel-input-vuetify'
export default {
components: {
VueTelInputVuetify,
},
...
And between my component's template tags I added this:
<VueTelInputVuetify
ref="phoneInput"
v-model="phoneNumber"
hint="Enter your phone number..."
:rules="phoneNumberRules"
placeholder=""
label="Phone"
:required="true"
:validate-on-blur="true"
:input-options="{showDialCode: true, tabIndex: 0}"
:valid-characters-only="true"
mode="international"
/>
Updated answer
I've tried it myself, working perfectly fine with:
Nuxt at 2.15.7
#nuxtjs/vuetify at 1.12.1 (vuetify at 2.5.7)
vue-tel-input-vuetify at 1.3.0.
Had to write this in my phone-input plugin
import Vue from 'vue';
import vuetify from "vuetify";
import VueTelInputVuetify from 'vue-tel-input-vuetify/lib';
Vue.use(VueTelInputVuetify, {
vuetify,
});
And I've imported it like this in nuxt.config.js
plugins: ['#/plugins/phone-input'],
With the following template
<template>
<vue-tel-input-vuetify v-model="phone"></vue-tel-input-vuetify>
</template>
<script>
export default {
data() {
return {
phone: ''
}
},
}
</script>
Here is a working github repo if you want to try it out by yourself.
Alternative idea
Looking at the documentation, it says that you need to transpile it (for Vue).
In nuxt.config.js, you could try the following to replicate the same need
build: {
transpile: [
'vue-tel-input-vuetify',
// 'vuetify' // this one may also be needed, try with and without
],
}

can't add npm package to nuxt js [vue-star-rating]

I'm new in nuxt js so when I try to add npm packages it won't work these are trials.
star-raing.js
import Vue from 'vue'
import StarsRatings from 'vue-star-rating'
Vue.use(StarsRatings)
nuxt.config.js
plugins: [{ src: '~/plugins/star-rating.js', mode: 'client' }],
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {},
transpile: ['star-rating']
}
it shows these errors
[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This
is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or
missing <tbody>. Bailing hydration and performing full client-side render.
[Vue warn]: Unknown custom element: <stars-ratings> - did you register the component correctly? For
recursive components, make sure to provide the "name" option.
found in
---> <Deals> at components/Home/Deals.vue
<Home> at pages/index.vue
<Nuxt>
<Default> at layouts/default.vue
<Root>
I had the same problem and here is the answer:
in your plugin (star-rating.js):
import Vue from 'vue'
import VueStarRating from 'vue-star-rating'
Vue.component('StarRating', VueStarRating)
note: You have to create 'star-rating.js' in your 'plugin'
folder
don't forget mode:'client' in your nuxt.config.js:
plugins: [
{
src: '~/plugins/star-rating.js', mode: 'client'
},
]
finally in your .vue file you can simply use :
<star-rating v-model="rating">
</star-rating>
ps: this is working for vuejs 2x
by the way if you want to get rating props you can simply access to it like this :
export default {
name:"example",
data() {
return {
rating: 0,
}
},
}
You should register it in your star-rating.js as follows:
import Vue from 'vue';
import StarsRating from 'vue-star-rating';
Vue.component('StarsRating', StarsRating);

"document is not defined" in Nuxt.js

I am trying to use Choices.js within a Vue component. The component compiles successfully, but then an error is triggered:
[vue-router] Failed to resolve async component default:
ReferenceError: document is not defined
In the browser I see:
ReferenceError document is not defined
I think this has something to do with the SSR in Nuxt.js? I only need Choices.js to run on the client, because it's a client only aspect I guess.
nuxt.config.js
build: {
vendor: ['choices.js']
}
AppCountrySelect.vue
<script>
import Choices from 'choices.js'
export default {
name: 'CountrySelect',
created () {
console.log(this.$refs, Choices)
const choices = new Choices(this.$refs.select)
console.log(choices)
}
}
</script>
In classic Vue, this would work fine, so I'm very much still getting to grips with how I can get Nuxt.js to work this way.
Any ideas at all where I'm going wrong?
Thanks.
It's a common error when you start a Nuxt project ;-)
The Choices.js lib is available only for client-side! So Nuxt tried to renderer from server-side, but from Node.js window.document doesn't exist, then you have an error.
nb: window.document is only available from the browser renderer.
Since Nuxt 1.0.0 RC7, you can use <no-ssr> element to allow your component only for client-side.
<template>
<div>
<no-ssr placeholder="loading...">
<your-component>
</no-ssr>
</div>
</template>
take a look at the official example here: https://github.com/nuxt/nuxt.js/blob/dev/examples/no-ssr/pages/index.vue
Update:
Since Nuxt >= 2.9.0, you have to use the <client-only> element instead of <no-ssr>:
<template>
<div>
<client-only placeholder="loading...">
<your-component>
</client-only>
</div>
</template>
To know more, see nuxt docs: https://nuxtjs.org/docs/2.x/features/nuxt-components#the-client-only-component
The accepted answer (while correct) was too short for me to understand it and use it correctly, so I wrote a more detailed version. I was looking for a way to use plotly.js + nuxt.js, but it should be the same as the OP's problem of Choice.js + nuxt.js.
MyComponent.vue
<template>
<div>
<client-only>
<my-chart></my-chart>
</client-only>
</div>
</template>
<script>
export default {
components: {
// this different (webpack) import did the trick together with <no-ssr>:
'my-chart': () => import('#/components/MyChart.vue')
}
}
</script>
MyChart.vue
<template>
<div>
</div>
</template>
<script>
import Plotly from 'plotly.js/dist/plotly'
export default {
mounted () {
// exists only on client:
console.log(Plotly)
},
components: {
Plotly
}
}
</script>
Update: There is <client-only> tag instead of <<no-ssr> in Nuxt v>2.9.0, see #Kaz's comment.
You need to add it as a plugin and then disable SSR for it.
As the document and window are not defined on the server-side.
Your nuxt.config.js should look like below
plugins: [
{ src: '~/plugins/choices.js' } // both sides
{ src: '~/plugins/client-only.js', mode: 'client' }, // only on client side
{ src: '~/plugins/server-only.js', mode: 'server' } // only on server side
],
I found that now the no-ssr is replace by , i am using echart and have the same problem but now it´s working!
<client-only>
<chart-component></chart-component>
</client-only>
I had this error with lightgallery.js adding mode: 'client'
seems helped
nuxt.config.js
plugins: [
{ src: '~/plugins/lightgallery.js', mode: 'client' }
],
plugins/lightgallery.js
import Vue from 'vue'
import lightGallery from 'lightgallery.js/dist/js/lightgallery.min.js'
import 'lightgallery.js/dist/css/lightgallery.min.css'
Vue.use(lightGallery)
ImageGallery.vue
<template>
<section class="image-gallery-container">
<div class="image-gallery-row">
<div
ref="lightgallery"
class="image-gallery"
>
<a
v-for="image in group.images"
:key="image.mediaItemUrl"
:href="image.mediaItemUrl"
class="image-gallery__link"
>
<img
:src="image.sourceUrl"
:alt="image.altText"
class="image-gallery__image"
>
</a>
</div>
</div>
</section>
</template>
<script>
export default {
name: 'ImageGallery',
props: {
group: {
type: Object,
required: true
}
},
mounted() {
let vm = this;
if (this.group && vm.$refs.lightgallery !== 'undefined') {
window.lightGallery(this.$refs.lightgallery, {
cssEasing: 'cubic-bezier(0.680, -0.550, 0.265, 1.550)'
});
}
}
}
</script>
<script>
import Choices from 'choices.js'
export default {
name: 'CountrySelect',
created () {
if(process.client) {
console.log(this.$refs, Choices)
const choices = new Choices(this.$refs.select)
console.log(choices)
}
}
}
</script>
I guess this should help, nuxt will touch insides of computed after it renders on server and window will be defined
This thread is a bit old, but I will leave my solution here so maybe someone finds it useful.
I had similar issue with vue-star-rating and few other plugins recently.
Below steps can be followed and adjusted depending on the plugin name, import / usage settings:
Go to your plugins folder and create new js file, in this case vue-star-rating.js, then edit it to setup the plugin:
import Vue from 'vue'
import VueStarRating from 'vue-star-rating'
Vue.component('vue-star-rating', VueStarRating); //<--- the name you used to register the plugin will be the same to use when in the component (vue-star-rating)
Go to your nuxt.config.js file and add plugin:
plugins: [{
src: '~/plugins/vue-star-rating', // <--- file name
mode: 'client'
},
//you can simply keep adding plugins like this:
{
src: '~/plugins/vue-slider-component',
mode: 'client'
}]
Now you are ready to use the plugin anywhere in the application. However, to do that you will need to wrap it in the container <client-only>. Example:
<client-only placeholder="loading...">
<vue-star-rating />
</client-only>
Notes:
You do not need to import anything locally to the component, simply using it like above should fix the problem.
Please make sure you are naming the plugin the same way in both places, step 1 and step 3. In this case it would be vue-star-rating.
if you still want to do it, document object can be taken this way:
const d = typeof document === 'undefined' ? null : document
For completeness, it's worth mentioning that instead of the object syntax in Yusuf Adeyemo answer (which I prefer as it separates out the file from how it is used), you can also set plugins to operate in client or server side only by naming the files like so:
export default {
plugins: [
'~/plugins/foo.client.js', // only in client side
'~/plugins/bar.server.js', // only in server side
'~/plugins/baz.js' // both client & server
]
}
src: https://nuxtjs.org/docs/directory-structure/plugins/#client-or-server-side-only
On top of all the answers here, you can also face some other packages that are not compatible with SSR out of the box (like in your case) and that will require some hacks to work properly. Here is my answer in details.
The TLDR is that you'll sometimes need to:
use process.client
use the <client-only> tag (be careful, it will not render but still execute the code inside)
use a dynamic import if needed later on, like const Ace = await import('ace-builds/src-noconflict/ace')
load a component conditionally components: { [process.client && 'VueEditor']: () => import('vue2-editor') }
With all of this, you're pretty much covered for every possible case.
I was trying to access document in created hook so when I moved the logic from created hook to mounted hook, my problem was solved.

Categories