How to use Toasted inside an export default {} - vue.js

I'm trying to use the package Toasted but I'm having a hard time understading how to use it.
I have a package called TreatErrors.js and I call this package to handle all errors from my application based on HTTP code returned by API a restfull API.
TreatErrors.js
import toasted from 'vue-toasted';
export default {
treatDefaultError(err){
let statusCode = err.response.status;
let data = err.response.data;
for(let field in data.errors){
if (data.errors.hasOwnProperty(field)) {
data.errors[field].forEach(message => {
toasted.show(message);
})
}
}
if(statusCode === 401){
toastr.error('Your token has expired. Please logout and login again to retrieve a new token');
}
return null;
},
}
and I'm tryin to call Toasted from within this package but I'm getting vue_toasted__WEBPACK_IMPORTED_MODULE_2___default.a.show is not a function. Any idea how I can use this Toasted inside of my own defined package?

The vue-toasted plugin must be registered with Vue first:
import Toasted from 'vue-toasted';
Vue.use(Toasted); // <-- register plugin
Then, your module could use it via Vue.toasted.show(...):
// TreatErrors.js
export default {
treatDefaultError(err) {
Vue.toasted.show(err.message);
}
}
And your Vue components could also use it via this.$toasted.show(...):
// Foo.vue
export default {
methods: {
showError(err) {
this.$toasted.show(err.message);
}
}
}

Related

Vue 3 get current application instance

How to access to current instance of application inside a component?
Option 1: Create a plugin
// define a plugin
const key = "__CURRENT_APP__"
export const ProvideAppPlugin = {
install(app, options) {
app.provide(key, app)
}
}
export function useCurrentApp() {
return inject(key)
}
// when create app use the plugin
createApp().use(ProvideAppPlugin)
// get app instance in Component.vue
const app = useCurrentApp()
return () => h(app.version)
Option 2: use the internal api getCurrentInstance
import { getCurrentInstance } from "vue"
export function useCurrentApp() {
return getCurrentInstance().appContext.app
}
// in Component.vue
const app = useCurrentApp()
In Vue.js version 3, you can access the current instance of an application inside a component using the getCurrentInstance() function provided by the Composition API.
Here's an example:
import { getCurrentInstance } from 'vue'
export default {
mounted() {
const app = getCurrentInstance()
console.log(app.appContext.app) // This will log the current instance of the application
}
}
Note that getCurrentInstance() should only be used in very specific situations where it's necessary to access the instance. In general, it's recommended to use the Composition API's reactive properties and methods to manage state and actions inside a component.

vue compile shared computed functions into separate package

How can i share common vue/nuxt specific code between different packages?
I do not want to use a monorepo however I have shared code that I want to separate into its own package. The shared code(new package), is written using #nuxtjs/composition-api and is just shared computed and methods used over and over in different components/templates.
I do not want the package to be setup as a plugin. Instead something to directly import to utilize tree shaking(just like the composition-api).
I am familiar with rollupjs to create the importable modules.
//New package
//index.js
export { default as isTrue } from './src/isTrue'
...
//src/isTrue
import { computed } from '#nuxtjs/composition-api'
export default (p) => {
return computed(() => p === 'true') //Im not 100% is this will break reactivity?!?!
}
I havent had any issues compiling this into .ssr, .esm, .min formats via rollupjs
The issue I come across is when i import the new package into a working file.
import { isTrue } from 'new-package'
export default{
name: 'testComp',
setup(props){
return {
isActive: isTrue(props.active)
}
}
will yield:
[vue-composition-api] must call Vue.use(VueCompositionAPI) before using any function.
i understand the #nuxtjs/composition-api is a wrapper of the VueCompositionAPI.
i dont really want to install the new package as a plugin therefore I have omitted the install on the new package(install ex: https://github.com/wuruoyun/vue-component-lib-starter/blob/master/src/install.js)
Used the options API
//library.js
export default function(){ // access to this -> arrow function doesnt have this
return this.disabled == true // when applied using the options api this will be the vue context aka property disabled
}
library.js is compiled using rollupjs and can be imported
//component.vue
import { isDisabled } from 'library'
export default {
//Composition API:
setup(props){
return {
//stuff
}
},
//Options API:
computed:{
isDisabled,
}
}

VueJS set base URL headers

I'm developing a system whose authentication based on tokens.
I successfully caught and saved the idToken inside the store.js.
Then I create a getter to return this idToken value:
returnToken(state) {
return state.idToken
}
Up to this everything is okay. I can see idToken value in both places (state and getters) through vue developer tools.
Then in the main.js I added a computed property:
export default {
computed: {
returnToken(){
return this.$store.getters.idToken
}
}
}
and Finally I added
axios.defaults.headers.common['Authorization']=this.returnToken
But Authorization header is undefined in the developer tools network.
How do I fix this and How do I know check whether or not it successfully reach to the main.js?
If you have a getter as follows:
returnToken(state){
return state.idToken;
}
Then in the component, access the getter using:
export default {
computed: {
returnToken(){
return this.$store.getters.returnToken; // was getters.idToken
// ^^^^^^^^^^^ --- changed this part
}
}
}
OR, in the component, access the state using:
export default {
computed: {
returnToken(){
return this.$store.state.idToken; // was getters.idToken
// ^^^^^ ------------ changed this part
}
}
}

How Can I correctly use dynamic variables in react-apollo graphql query?

I have an apollo-wrapped component that's supposed to provide my component with response data from the github graphql v4 api. I intend to use a string(SEARCH_QUERY) from another part of the app to be used in my gql query but github keeps returning undefined. I am following offical apollo docs http://dev.apollodata.com/react/queries.html#graphql-options.
I dont see what I am doing wrong.
import React, { Component } from 'react';
import { Text, FlatList } from 'react-native';
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
import { SEARCH_QUERY } from './Home' // this is a string like "react"
// The data prop, which is provided by the wrapper below contains,
// a `loading` key while the query is in flight and posts when ready
const ReposList = ({ data: { loading, search }}) => <Text>SearchResults</Text>
// this doesnt work because I cant properly inject 'SEARCH_QUERY' string
const searchRepos = gql`
query searchRepos($type: searchType!, $query: String!) {
search(type: REPOSITORY, query: $query, first: 100) {
edges {
node {
... on Repository {
nameWithOwner
owner {
login
}
}
}
}
}
}
`
// The `graphql` wrapper executes a GraphQL query and makes the results
// available on the `data` prop of the wrapped component (ReposList here)
export default graphql(searchRepos, {
options: { variables: { query: SEARCH_QUERY }, notifyOnNetworkStatusChange: true }
}
)(ReposList);
This query without variables works well and returns search results as expected. straight forward, right?
const searchRepos = gql`{
search(type: REPOSITORY, query: "react", first: 100) {
edges {
node {
... on Repository {
nameWithOwner
owner {
login
}
}
}
}
}
}
`
When this is used github returns undefined.
const searchRepos = gql`
query searchRepos($type: searchType!, $query: String!) {
search(type: REPOSITORY, query: $query, first: 100) {
edges {
node {
... on Repository {
nameWithOwner
owner {
login
}
}
}
}
}
}
`
Your query is erroring out because you've defined a variable $type -- but you don't actually use it inside your query. You don't have to actually send any variables with your query -- you could define one or more in your query and then never define any inside the graphql HOC. This would be a valid request and it would be up to the server to deal with the undefined variables. However, if you define any variable inside the query itself, it has to be used inside that query, otherwise the query will be rejected.
While in development, you may find it helpful to log data.error to the console to more easily identify issues with your queries. When a query is malformed, the errors thrown by GraphQL are generally pretty descriptive.
Side note: you probably don't want to use a static values for your variables. You can calculate your variables (and any other options) from the props passed down to the component the HOC is wrapping. See this section in the docs.
const options = ({someProp}) => ({
variables: { query: someProp, type: 'REPOSITORY' },
notifyOnNetworkStatusChange: true,
})
export default graphql(searchRepos, {options})(ReposList)

vue bestpractice api handling

Been reading the docs and googling around for best practice to handle api calls in bigger projects without luck (or ateast not what Im searching for).
I want to create a service / facade for the backend that I can load in every component that needs it. For exampel.
I want to fetch historical data for weather in a service so in every component I need this I can just load the weather-serivce and use a getter to fetch the wanted data. I would like to end up with something like below. But I dosent get it to work. So I wonder, what is best practice for this in vue.js?
import WeatherFacade from './data/WeatherFacade.vue'
export default {
name: 'Chart',
created () {
console.log(WeatherFacade.getWeather())
},
components: {
WeatherFacade
}
}
ps. using vue 2.1.10
It could be easily done by creating some external object that will hold those data and module bundling.What I usually do in my projects is that I create services directory and group them in order I want.
Let's break it down - services/WeatherFascade.js (using VueResource)
import Vue from 'vue'
export default {
getWeather() {
return Vue.http.get('api/weather')
}
}
If you have to pass some dynamic data such as ID, pass it as just parameter
import Vue from 'vue'
export default {
getWeather(id) {
return Vue.http.get(`api/weather/${id}`)
}
}
Then in your component you can import this service, pass parameters (if you have them) and got data back.
import WeatherFascade from '../services/WeatherFascade'
export default {
data() {
return {
weatherItems: []
}
},
created() {
this.getWeatherData()
},
methods: {
getWeatherData() {
WeatherFascade.getWather(// you can pass params here)
.then(response => this.weatherItems = response.data)
.catch(error => console.log(error))
}
}
}
You can use any library for that you like, for instance axios is cool.