How to use Axios globally using composition API - vue.js

I'm having trouble getting Axios to work using the composition API. The following is what I've done, but I'm unsure how to access Axios within setup(). I'm aware that the "this" keyword is no longer available in the composition API.
Created an axio.js file in /plugins:
import axios from 'axios'
export default {
install: (app, options) => {
app.config.globalProperties.axios = axios.create({
baseURL: options.baseUrl,
withCredentials: true,
headers: {
Authorization: options.token ? `Bearer ${options.token}` : '',
}
})
}
}
Added it to plugins/index.js
import { loadFonts } from './webfontloader'
import vuetify from './vuetify'
import pinia from '../store'
import router from '../router'
import axios from './axios'
export function registerPlugins (app) {
loadFonts()
app
.use(vuetify)
.use(pinia)
.use(router)
.use(axios, { baseUrl: import.meta.env.VITE_AXIOS_BASE_URL })
}
Then the main.js file registers all plugins:
import App from './App.vue'
// Composables
import { createApp } from 'vue'
// Plugins
import { registerPlugins } from '#/plugins'
const app = createApp(App)
registerPlugins(app)
app.mount('#app')

Related

I need change vue resources to axios

I'm creating an application based on this code from github.
I need change vue resources to axios, how i can do that ?
I would like to know how to do this keeping the structure of this code.
I'm using vue 3.
Anyone who can help would be very grateful :)
the full code i'm modifying: here
http:
import Vue from 'vue'
import VueResource from 'vue-resource'
import services from './services'
Vue.use(VueResource)
const http = Vue.http
http.options.root = 'https://localhost.com/api'
Object.keys(services).map(service =>{
services[service] = Vue.resource('', {}, services[service])
})
export { http }
export default services
http services:
import { services as auth } from '#/modules/auth'
export default {
auth
}
Actions:
import services from '#/http'
import * as types from './mutation-types'
export const ActionDoLogin = (context, payload) =>{
return services.auth.login(payload)
}
export const ActionSetUser = ({ commit }, payload) => {
commit(types.SET_USER, payload)
}
export const ActionSeToken = ({ commit }, payload) => {
commit(types.SET_TOKEN, payload)
}
Services:
export default {
login: { method: 'post', url: 'login' }
}
Main:
import { createApp } from 'vue'
import App from './App'
import router from './router'
import store from './store'
import './assets/scss/app.scss'
createApp(App).use(store).use(router).mount('#app')
Login view:
<script>
import {mapActions} from 'vuex'
export default {
data: () =>({
form:{
email:'',
pass:''
}
}),
methods:{
...mapActions('auth', ['ActionDoLogin']),
submit(){
this.ActionDoLogin(this.form).then(res =>{
console.log(res.data)
})
}
}
}
</script>

Property 'axios' does not exist on type

It's my first time trying to use Vue and I've run into some troubles with axios. I have installed and imported it as per instructions on the website.
But when I'm trying to use it, I'm getting an error
TS2339: Property 'axios' does not exist on type 'TodoList'.
Here's my main.ts
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
createApp(App).use(VueAxios, axios).use(ElementPlus).mount('#app')
And the TodoList with which I have a problem
<template>
<h1>Todo List</h1>
<todo-form #send-message="createTodo"></todo-form>
</template>
<script lang="ts">
import { ElMessage } from 'element-plus';
import { Options, Vue } from 'vue-class-component';
import TodoForm from './TodoForm.vue'
#Options({
components: {
TodoForm,
}
})
export default class TodoList extends Vue {
todos = [];
async mounted() {
await this.loadTodos();
}
async loadTodos() {
const response = await this.axios.get('http://localhost:8080/');
this.todos = response.data;
}
async createTodo(todo: any) {
console.log("Todo", todo)
ElMessage({
message: "Todo Created",
type: "success"
})
}
}
</script>
Any help is appreciated
It turned out that axios should be installed directly in application folder. Problem solved :)

Vuex 4 Modules can't use global axios property

I have a Vue3 (without Typescript) app running Vuex 4.0.0.
I'm trying to set up a simple GET request in one of my store modules using axios, however I'm getting a Cannot read property of 'get' of undefined when I try to do it via an action called in one of my components, however if I call this.$axios from the component it works fine. For some reason, my modules can't use this.$axios, while elsewhere in the app I can.
I've declared $axios as a globalProperty in my main.js file.
// main.js
import { createApp } from "vue";
import App from "./App.vue";
import { router } from "./router";
import { store } from "./store";
import axios from "axios";
const app = createApp(App).use(store).use(router);
app.config.globalProperties.$axios = axios;
app.mount("#app");
And the store module looks like this (simplified for the purposes of this question):
// store/modules/example.js
const state = () => ({
message: ""
});
const mutations = {
getMessage(state, payload) {
state.message = payload;
}
};
const actions = {
async setMessage(commit) {
this.$axios.get("example.com/endpoint").then(response => {
commit("setMessage", response.message);
});
}
};
export default {
namespaced: true,
state,
getters,
actions,
mutations
};
The main store/index.js that's getting imported in main.js above looks like this:
// store/index.js
import "es6-promise";
import { createStore } from "vuex";
import example from "./modules/example";
export const store = createStore({ modules: { example } });
In the component, I have the following:
// MyComponent.vue
import { mapGetters, mapActions } from "vuex";
export default {
computed: {
...mapGetters({
message: "example/getMessage"
})
},
methods: {
...mapActions({
getMessage: "example/setMessage"
})
}
};
And a simple button with #click="getMessage". Clicking this button, however, returns Uncaught (in promise) TypeError: Cannot read property 'get' of undefined, but if I copy/paste the setMessage action into a component method, it works just fine.
Is there a way for me to expose this.$axios to the store files?
While this is not the ideal solution, as I would've preferred to have my $axios instance available globally with a single declaration in the mount file, it's probably the next best thing.
I made a lib/axiosConfig.js file that exports an axios instance with some custom axios options, and I just import that one instance in every module that needs it.
import axios from "axios";
axios.defaults.baseURL= import.meta.env.DEV ? "http://localhost:8000": "example.com";
axios.defaults.headers.common["Authorization"] = "Bearer " + localStorage.getItem("token");
axios.defaults.headers.common["Content-Type"] = "application/json";
// etc...
export const $axios = axios.create();
And in whatever module I need $axios in, I just import { $axios } from "./lib/axiosConfig. It's not perfect as I mentioned, since I do still have to import it in every module, but it's close enough as far as I can see, and has the added benefit of using the same axios config everywhere by just importing this file.

Have to import axios in any *.vue file of vue/cli 4.0.5 app

In my #vue/cli 4.0.5 app in any *.vue file I have to import axios, if I need to use it on this page, like:
<script>
import {bus} from '../../../src/main'
import appMixin from '#/appMixin'
import axios from 'axios'
...
But I expected axios to be accessible in *.vue file of my app.
In src/main.js I have defined :
import router from './router'
import store from './store'
import axios from 'axios'
...
Vue.use(axios)
moment.tz.setDefault(settingsTimeZone)
export const bus = new Vue()
axios.defaults.crossDomain = true
Vue.config.productionTip = false
Vue.prototype.$http = axios
I have this question as priorly I worked in laravel 5 / vuejs 2.6 app I have axios was accessible in all *.vue files of my app
without any definition...
Why so and if I have to write
import axios from 'axios'
in any file where I need axios ?
UPDATED BLOCK :
In my src/main.js I tried and failed as :
...
import axios from 'axios'
export const bus = new Vue()
axios.defaults.crossDomain = true
// axios.withCredentials = true
// window.axios.defaults.baseURL = window.App.baseurl;
Vue.config.productionTip = false
Vue.prototype.$http = axios
const token = localStorage.getItem('token')
if (token) {
Vue.prototype.$http.defaults.headers.common['Authorization'] = token
}
// home url in .env file
let apiUrl = process.env.VUE_APP_API_URL
alert( '++apiUrl::'+apiUrl ) // CHECK IT VALID URL
new Vue({
router,
store,
bus,
render: h => h(App)
}).$mount('#app')
Vue.use({
install (Vue) {
Vue.prototype.$api = axios.create({
baseURL: apiUrl // !!!
})
}
})
router.afterEach((to, from) => {
bus.$emit('page_changed', from, to)
})
But next in my component I commented line with axios import:
<script>
import {bus} from '../../main'
// import axios from 'axios'
import Vue from 'vue'
...
export default {
data: function () {
return {
...
}
}, // data: function () {
mounted() {
this.loadTasksData()
}, // mounted() {
methods: {
loadTasksData() {
let apiUrl = process.env.VUE_APP_API_URL
let config = {
withCredentials: true,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
}
}
axios({url: apiUrl + '/tasks_paged/' + this.current_page, data: {}, method: 'get', config: config})
.then(response => { // Error here!
I got error :
vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in mounted hook: "ReferenceError: axios is not defined"
...
What is wrong? Did I put your construction in valid place?
Also could you please give more explanations (or provide a link) about this construction? It is about my expiarence ...
Thanks!
Try this:
Vue.use({
install (Vue) {
Vue.prototype.$api = axios.create({
baseURL: 'PUT A BASE URL IF YOU WANT'
})
}
})

Import Axios Method Globally in Vuejs

this is my ~/plugins/axios.js file:
import axios from 'axios'
let api = axios.create({
baseURL: 'http://localhost:8000/api/v1/'
})
export default api
When I want to use axios in every components, I must have write this line:
import api from '~/plugins/axios
How can i config it globally, just write $api instead?
You can create a plugin and use it like this in your main.js file (if you're using something like vue-cli)
import axios from 'axios'
Vue.use({
install (Vue) {
Vue.prototype.$api = axios.create({
baseURL: 'http://localhost:8000/api/'
})
}
})
new Vue({
// your app here
})
Now, you can do this.$api.get(...) on every component method
Read more about Vue plugins here: https://v2.vuejs.org/v2/guide/plugins.html
Provide/Inject could be an option as well: https://v2.vuejs.org/v2/api/#provide-inject
There is a window object available to you in the browser. You can actively leverage that based on your requirements.
In the main.js file
import axiosApi from 'axios';
const axios = axiosApi.create({
baseURL:`your_base_url`,
headers:{ header:value }
});
//Use the window object to make it available globally.
window.axios = axios;
Now in your component.vue
methods:{
someMethod(){
axios.get('/endpoint').then(res => {}).catch(err => {});
}
}
This is basically how I use axios globally in my projects. Also, this is also how Laravel uses it.
Keeping this in main.js works perfectly fine for me in Vue 3.
import { createApp } from 'vue';
import App from './App.vue';
import axios from "axios";
const app = createApp(App);
const instance = axios.create({
baseURL: 'https://example.com/',
});
app.config.globalProperties.axios=instance
app.mount('#app');
and to use it in any component,
this.axios.post('/helloworld', {
name: this.name,
age: this.age
})