Incorporate a globally imported class inside a Vue 3 component by utilizing the provide function

In the process of developing an application using Vue 3, I have created an api class specifically for handling API calls:

import axios from 'axios'

export default class {

    /**
     * Send GET Request
     * @param  {string} url
     * @return {Promise}
     */
    get(url) {
        return new Promise((resolve, reject) => {
            axios.get(url, {}).then(response => {
                if (response.status === 200) {
                    return resolve(response);
                }
            }).catch((error) => {
                return reject(error);
            })
        });
    }

    /**
     * Send POST Request
     * @param  {string} url
     * @param  {object} payload Data object to send
     * @return {Promise}
     */
    post(url, payload) {
        return new Promise((resolve, reject) => {
            axios.post(url, payload, {}).then(response => {
                if (response.status === 200) {
                    return resolve(response);
                }
            }).catch((error) => {
                return reject(error);
            })
        });
    }

    /**
     * Send FIND Request
     * @param  {string} url
     * @return {Promise}
     */
    find(url) {
        return new Promise((resolve, reject) => {
            axios.get(url, {}).then(response => {
                if (response.status === 200) {
                    return resolve(response);
                }
            }).catch((error) => {
                return reject(error);
            })
        });
    }

}

To use the functions in this class within my Vue components, I imported the _api.js file and included .provide('$api', apis) in the createApp function within the app.js file:

import { createApp, h } from 'vue';
import { createInertiaApp } from '@inertiajs/inertia-vue3';
import api from './Models/_api'

const apis = new api();

createInertiaApp({
    resolve: (name) => require(`./Pages/${name}.vue`),
    setup({ el, app, props, plugin }) {
        return createApp({ render: () => h(app, props) })
            .use(plugin)
            .mixin({ methods: { route } })
            .provide('$api', apis)
            .mount(el);
    },
});

In one of my components, I am utilizing it as follows:

<template>
   //HTML Files
</template>
export default {
    data(){
        return{
            tableData:[],
        }
    },
    methods:{
        fetchData(){

            this.$api.post('/api/user-data', {}).then(response=>{
                if(response.status === 200)
                {
                    this.tableData = response.data.data
                }
            });
        }
    },
    created(){
        this.fetchData();
    },
}
</script>

However, when attempting to use this.$api, an error is thrown:

TypeError: Cannot read properties of undefined (reading 'post')

The issue persists even after trying console.log(this.$api) which returns undefined

In contrast, the following approach worked effectively in Vue 2:

Back when I was working with Vue 2, everything functioned perfectly fine by simply initializing the class in app.js and adding it to the prototype.

Sample Vue 2 Code snippet from app.js:

import { App, plugin } from '@inertiajs/inertia-vue'
import Vue from 'vue'
import api from './Models/_api'

const apis = new api();
Vue.prototype.$api = apis;

const el = document.getElementById('app')

new Vue({
    store: store,
    render: h => h(App, {
        props: {
            initialPage: JSON.parse(el.dataset.page),
            resolveComponent: name => import(`NitsPages/${name}`).then(module => module.default),
        },
    }),
}).$mount(el)

Answer №1

Vue3 has a specific rule regarding the use of prefixes like _ and $.

Any properties that begin with _ or $ will not be proxied on the component instance to avoid conflicts with Vue's internal properties and API methods. These properties must be accessed using this.$data._property.

For example, try:

this.$data.$api.post(...)

In my opinion, reserving these commonly used prefixes for internal purposes may not have been the best decision. However, that's how it currently stands. More information can be found here.

Answer №2

One way to make your API Class accessible globally in Vue 3 is by setting it as a global property of your Vue instance.

This approach is outlined in the Vue 3 Application Documentation.

For example:

main.js

import { createApp, h } from 'vue';
import { createInertiaApp } from '@inertiajs/inertia-vue3';
import api from './Models/_api'

const apis = new api();

createInertiaApp({
    resolve: (name) => require(`./Pages/${name}.vue`),
    setup({ el, app, props, plugin }) {
        const app = createApp({ render: () => h(app, props) });
        app.config.globalProperties.api = apis;
        return 
            .use(plugin)
            .mixin({ methods: { route } })
            .provide('$api', apis)
            .mount(el);
    },
});

By doing this, you can easily access your API anywhere within your Vue components using this.API

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Enhance Your jQuery Experience with Advanced Option Customization

I am currently developing a plugin that deals with settings variables that can be quite deep, sometimes reaching 3-4 levels. Following the common jQuery Plugin pattern, I have implemented a simple method for users to update settings on the go using the not ...

What steps can I take to stop my browser from displaying the "waiting for MyHostName" message while performing an ajax Post/Get operation?

Whenever I access a website using Chrome, a message appears in the status bar saying "Waiting for MyHost name" along with an Ajax Loader circle in the browser tab. Here is a javascript function that I am working with: function listen_backend_client_reques ...

Is there a lifecycle function in React Native that runs when the app is not actively being used or is in the background?

Is there a function in react native that runs continuously even when the app is not being used or in background mode? I am looking for a lifecycle function in react-native that operates even when the user is not actively using the app or when the app is r ...

JavaScript / Ajax / PHP - A Minor Bug That's Bugging Me

I'm in need of some help, as I feel like I'm losing my mind right now. I've developed a code using php/js/ajax to verify if an email address exists when it's submitted. After testing the ajax, I can confirm that the correct values are ...

How can you identify errors in serialization when working with Web API endpoints?

There are times when I have an endpoint set up on my web API: [HttpPost] public async Task Foo([FromForm] int[] a, [FromForm] int b, ...) { await Task.Delay(1000); } When I make a call to this endpoint from the client side using axios: var formData = ...

Is it possible for the logo in the div and the height of the div to vanish after 10 seconds?

Is it possible to conceal a div along with its logo? I currently have a jpeg logo displayed at the top of my website, but I would like it to vanish after 10 seconds and have the text below it shift upward to fill the space. I've managed to hide the ...

Pass a customized field as an argument to the .find() method in mongoose

When making an HTTP call to my api to fetch documents from a mongodb, I include two parameters in the URL: campo and keyphrase. My goal is to retrieve all documents where the parameter campo is set to my specified keyphrase. For example, if I have some doc ...

Enhance Your AngularJS Application with Data Transfer Object Models

Is there a way to implement a Data Transfer Object (DTO)? In my backend code, I have clearly defined domains such as the Client class: class Client { protected $firstName; protected $lastName; } This class contains specific properties that I wan ...

What steps should I take to address the ES6 promise chain issue within Express?

Currently, I am delving into Promise chaining and experimenting with some code involving express and mongoose in a node environment. Below is the snippet of code that I am working on: const register = (req, res, next) => { User.findOne(req.params.ema ...

Extracting repeated information from a form_for select box using jQuery looped through

How can I duplicate the output of a Rails loop and display it in a different section of the webpage? This is the ERB code I am currently using: <%= form_for @order do |f|%> <div class="col-xs-6"> <%= f.fields_for :units, @orde ...

Deselect all checkboxes other than the daily selection

I recently designed an E-commerce website that includes a package customization feature where users can modify their packages. The initial question presents three radio button options: 1. Daily 2. Weekly 3. Monthly If the user selects 'daily&apos ...

"Exploring the concept of object occlusion with transparent elements in

Is it possible to create an object in a three.js scene that is invisible but still acts as if it's blocking other objects? For example, say we have objects a, b, and c in the scene along with a camera. I want object c to be unseen by the camera, yet s ...

What is the process of emphasizing a WebElement in WebdriverIO?

Is there a way to highlight web elements that need to be interacted with or asserted in webdriverIO? Or is there a JavaScript code similar to the javascript executor in Selenium that can be used for this purpose? ...

An error occurs due to attempting to parse the data using JSON.parse

Trying to troubleshoot a seemingly simple issue: The callback function of an AJAX post request is receiving a JSON string in the 'data' parameter. {"result":"Torte"} Manually parsing it yields the expected result: var response = JSON.parse(&ap ...

Experience the power of live, real-time data-binding for date-time input with AngularFire in 3 different

Here is a simplified version of my code snippet: tr(ng-repeat='entry in ds3.entries | orderBy:orderByField:reverseSort | filter:query as results') td input.screen(type='datetime-local', ng-model='entry.date_recei ...

Unable to view options in Vuetify's v-select component

Having an issue with a component that is supposed to grab the address from a user, specifically the state. Despite following the documentation closely, I am unable to figure out why the options are not visible when clicking the button. It works fine when ...

Is the communication between Laravel and Vue always done through RESTful APIs?

Throughout my years of coding experience, I have integrated various software services into applications using API documentation provided by the software owners. Initially, I believed that APIs were simply a means for facilitating communication between diff ...

use dotenv in your Build Folder

Is it possible to have my .env file in my React JS project move to the build folder when I run NPM build command? If so, how can this be achieved? If not, what would be the alternative solution? I attempted using "build": "cp .env.template ...

Executing PHP function through AJAX

I have thoroughly researched various resources regarding my issue but still have not been able to find a solution. My goal is to retrieve the result of a PHP function using jQuery AJAX. function fetch_select(){ val_name = $('#name').val(); ...

How to iterate through a Vue data object using forEach loop

I am currently working with a variable in my data: data: function () { return { myVariable: false, } } I'm trying to figure out how to access this variable within a looping function, like the example below: anArray.forEach(functi ...