How to use vue-toastification - javascript

I just migrated my project created in vue 3 to nuxt 3. Previously I used the vue-toastification module but now I don't know how to import it correctly. My code using this module.
import { useToast, POSITION } from 'vue-toastification'
const toast = useToast()
export default {
methods: {
copy(text) {
toast.success('Copied!', {
timeout: 2000,
position: POSITION.BOTTOM_CENTER,
})
navigator.clipboard.writeText(text)
}
}
}
In Vue I had to do app.use(Toast) but Nuxt does not have an index.js file. Adding modules: ['vue-toastification/nuxt'] in nuxt.config.js does not work because I get an error.

Answers suggested by kissu and Ricardo de Paula worked for me while I was using development server (npm run dev).
After building and running the project I encountered error 500:
Named export 'useToast' not found. The requested module 'vue-toastification' is a CommonJS module, which may not support all module.exports as named exports. CommonJS modules can always be imported via the default export, for example using: import pkg from 'vue-toastification';
To fix this, I registered toast as plugin helper (I'm using Nuxt 3.1.1 with Nitro 2.1.1):
Inside vue-toastificaton.client.js:
import { defineNuxtPlugin } from '#app'
import * as vt from 'vue-toastification'
import '#/assets/css/toast.scss'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(vt.default)
return {
provide: {
toast: vt.useToast()
}
}
})
Then in my component script setup:
//throws an error after production build
//import { useToast } from 'vue-toastification'
//const toast = useToast()
//toast.success('Yay!!!')
//works after production build
const { $toast } = useNuxtApp()
$toast.success('Yay!!!')

If you want it to be available globally, you can install it as a Nuxt plugin as explained in the official docs or in this other answer.
vue-toastification is probably a client-side only plugin, hence you would probably want to use it as
/plugins/vue-toastificaton.client.js like this
import { defineNuxtPlugin } from '#app'
import Toast from "vue-toastification"
import "vue-toastification/dist/index.css" // if needed
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.vueApp.use(Toast)
})
Then, you should be able to use it in your components with either Composition API or Options API (I think).

I was wanting to do the same thing. I read kissu's answer and did the following:
1 - I created a folder for the puglin - plugins
2 - Inside the plugins folder I created a file called vue-toastificaton.client.js
Inside vue-toastificaton.client.js:
import { defineNuxtPlugin } from '#app'
import Toast from 'vue-toastification'
import 'vue-toastification/dist/index.css' // if needed
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(Toast)
})
And I used it that way:
<script setup>
import { useToast } from 'vue-toastification'
const toast = useToast()
const onSubmit = () => {
// use the toast notification plugin to show a success message
toast.success('Hello world!')
}
</script>

Related

Vue 3's Provide / Inject using the Options API

I've been trying to follow the documentation for the API on the Vue 3 website which says to use app.provide('keyName',variable) inside your main.js file like so:
import App from './App.vue'
import { createApp } from 'vue'
import axios from 'axios'
const app = createApp(App)
app.provide('axios', axios)
app.use('Vue')
app.mount('#app')
Then inject and use it in your child component like so:
export default {
inject: ['axios'],
...
createUser (data) {
return this.axios.post('/users', data)
}
}
However doing so just gives me this error in my console:
Uncaught TypeError: Cannot read properties of undefined (reading 'post')
Is there anything I'm missing? I didn't see any about an import unless you're using the Composition API. Can provide / inject be called from within a .js file? I would expect so as long as its within a export default {} statement
Ive tried following the API to a "T" but it simply refuses to work for me. Also tried searching the web for solutions but everything I've found says what I'm doing should be working just fine.
It works, see the playground.
But is not absolutely necessary, since with the browser library version axios is globally defined and could be accessed also without inject
You could also save yourself some time with the vue-axios plugin.
Example
const { createApp } = Vue;
const myComponent = {
inject: ['axios'],
created() {
this.axios.get('/')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
},
template: '<div>My Component</div>'
}
const App = {
components: {
myComponent
}
}
const app = createApp(App)
app.provide('axios', axios)
app.mount('#app')
<div id="app">
<my-component></my-component>
</div>
<script src="https://unpkg.com/vue#3/dist/vue.global.js"></script>
<script src="https://unpkg.com/axios#1.3.1/dist/axios.min.js"></script>

There is no active component instance at vue 2.7

I am using vue 2.6.14 + composition-api 1.6.2
I want to upgrade the app as vue 2.7 (surely, remove composition-api)
I am using two repositories,
one is the main and the other is UMD library.
(both use vue, vue-cli)
The problem is, it looks like there is no active instance at UMD library.
Please look below codes
// repo B(the UMD library) > someComponent.vue
<template>
...
</template>
<script>
import { getCurrentInstance } from 'vue';
export default {
...
setup() {
const vm = getCurrentInstance();
console.log(vm); // <- null
...
onMounted(...); // <- [Vue warn] onMounted is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup().
}
}
// repo A(the main) > somePage.vue
<template>
...
<someComponent>...</someComponent>
</template>
<script>
import { getCurrentInstance } from 'vue';
import { someComponent } from '#some-company/design-system';
...
export default {
...
components: {
someComponent
},
setup() {
const vm = getCurrentInstance();
console.log(vm); // <- VueComponent (It works well!)
...
onMounted(...); // No warning has logged (It works well!)
}
}
Thanks for your answer.

export import browser complaint cannot find module

This Meteor app has a template event that maks a Meteor.call, and is causing browser error Cannot find module 'server/plateCheck.js'. The file responsible is:
//app/imports/api/vehicles/methods.js
import { Meteor } from 'meteor/meteor'
import { Vehicles } from './vehicles.js'
import { plateCheck } from "../server/plateCheck.js"; //<<<<<<<<<<
Meteor.methods({
'extractPlateData': function (plate) {
console.log('method called: ', plate)
plateCheck(plate)
}
)},
//app/imports/api/vehicles/server/plateCheck.js
import {Vehicles} from '../imports/api/vehicles/vehicles.js'
const plateCheck = async (plateNumber) => {...}
module.exports = plateCheck;
meteor list includes ecmascript 0.15.1
Why is this and isn't the export/import correct as stated? How to get read of the error? Thanks.
Your relative path is wrong. The server folder is in the same directory as methods.js, so you'll need to import
import { plateCheck } from "./server/plateCheck.js";
Or you can make all imports absolute:
//app/imports/api/vehicles/methods.js
import { plateCheck } from "/imports/api/server/plateCheck.js";
...
//app/imports/api/vehicles/server/plateCheck.js
import {Vehicles} from '/imports/api/vehicles/vehicles.js'

How do I group functions in ES6 Modules?

How do you group functions in a ES6 Module package? In CommonJS packages you can do this.
// package.js
const startSession = require("./startSession");
module.exports = {
hooks: {
startSession,
},
};
// client.js
const { hooks: {startSession } } = require("package");
// OR
const { startSession } = require("package").hooks;
It looks like the similar syntax in ES6 code isn't supported.
import { hooks: {startSession } } from "packageX";
On source for that, is this babel issue from 2016. https://github.com/babel/babel/issues/4996
Another is the official documentation, that doesn't really mentioning this kind of syntax.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
Solutions
One solutions in ES6 javascript is this.
// package.js
import startSession from "./hooks/start-session";
export const hooks = {
startSession
};
// client.js
import { hooks } from "package";
const { startSession } = hooks;
But I would like to write the import in one line. Maybe not possible?
This is not what I look for.
import { hooks } from "package"; const { startSession } = hooks;
This kind of syntax would be nice, but how do you set up the packages, if possible?
import { startSession } from "packageX/hooks";
import { startSession } from "packageX".hooks;
Any other suggestions?
Answer
Estus below pushed me in the right direction. Here is a more detailed answer.
// package.json
"main": "src/index.js",
"exports": {
".": "./src/index.js",
"./hooks": "./src/hooks/index.js",
}
// src/hooks/start-session.js
export default () => {}
// src/hooks/index.js
export * as startSession from "./start-session";
// src/index.js
export const doSomething () => {}
// client.js
import { doSomething } from "packageX";
import { startSession } from "packageX/hooks";
ES modules are supposed to be statically analyzed so nested imports that result from expressions are impossible. Import syntax isn't destructuring, just looks similarly. It is strictly specified; if a feature isn't there, it's not supported.
This should be preferably avoided as this prevents hooks properties from being tree-shaken (not applicable to Node currently).
For an entry point or barrel module, prefixes can be used to give an export a scope:
export { default as hookStartSession } from "./hooks/start-session";
And this is a way this is usually done when an import has some scope, at least if a package exposes additional public entry point.
import { startSession } from "packageX/hooks"

Allow export of Client, Server and Common modules independently in a single typescript npm package

I have a project (lets call it FlatEarth) with client-only, server-only and common components. I would like to create a single npm package that allows importing from only the relevant portions.
For example, a client-side only project would be able to do the following:
import { FeCommon, FeClient } from 'FlatEarth'.
The issue that I am facing is that even though I am only importing the FeClient and FeCommon components, the FeServer components (request-promise) will cause errors in the build process (since they are not compatible with client solutions) since they are still being imported by FlatEarth's index.ts file.
The FlatEarth setup is essentially:
index.ts
import * as FeCommonStatic from './FeCommon';
import * as FeServerStatic from './FeServer';
import * as FeClientStatic from './FeClient';
export { FeCommonStatic as FeCommon };
export { FeServerStatic as FeServer };
export { FeClientStatic as FeClient };
FeCommon.ts
import * as stringStatic from './String';
import * as uriStatic from './Uri';
export { stringStatic as string };
export { uriStatic as uri };
FeServer.ts
import { ServerRequestHandler } from './Server/ServerRequestHandler'; // Depends on request-promise.
export { ServerRequestHandler as RequestHandler }
FeClient.ts
import { ClientRequestHandler } from './Client/ClientRequestHandler'; // Depends on jquery
export { ClientRequestHandler as RequestHandler }

Categories

Resources