Discover the steps to dynamically set global data in Vue during runtime

I am currently working on a Vue application that requires fetching data from JSP at runtime, which means I cannot use .env files. As a solution, I am attempting to set data in Vue that can be accessed throughout the entire application (components, mixins, ts modules, etc). The Vue prototype seems like a good option and it works for the Vue application, but I am facing difficulty accessing it in ts modules.

import Vue from 'vue'
import App from '@/App.vue'

class VueInstance {
  data: any

  constructor () {
    this.data = {}
  }

  public setData(key: string, data: any) {
    this.data[key] = data
    return this
  }

  public init() {
    Vue.prototype.$GLOBAL_DATA = this.data

    new Vue({
      render: (h) => h(App),
    }).$mount('app')
  }
}

export default function createVueInstance() {
  return new VueInstance()
}

This is my JSP file where I initialize the application and pass some data:

<div id="app"></div>

<%
    String javaVar = "javaVar";
%>

<aui:script require="<%= mainRequire %>">
    main
    .default('app')
    .setData('foo', 'foo')
    .setData('bar', 'bar')
    .setData('javaVar', '<%= javaVar %>')
    .init()
</aui:script>

Here is an example of a ts module where I need to access my global data:

const apiUrl = $GLOBAL_DATA // coming from prototype or elsewhere.

export default {
   getData() {
      return axios.get(`${apiUrl}/foo`)
   }
}

Answer №1

There are numerous approaches to tackle this issue.

One way is to define the problem as such: The backend holds information (like the api baseUrl) that the frontend (JavaScript application) needs access to.

Option 1: Transmitting data through the window object.

// backend
<div id="app"></div>

<script>
// backendvariable could be a string
// we could even JSON-encode the data

window.APP_CONFIG = <%= backendVariable %>

// alternatively:
window.APP_CONFIG = {
    API_URL: <%= apiUrl %>,
    SOME_CONSTANT: <%= someConstant %>,
    ...
}
</script>
// somewhere in our frontend
const apiUrl = window.APP_CONFIG.API_URL;

Option 2: Providing data through the Vue instance If your JavaScript bundle only consists of defined components and leaves the Vue mounting process to your backend.

// backend
<div id="app"></div>

<script>
new Vue({ 
   el: '#app',
   data: {
      API_URL: <%= backendVariable %>
   }
});
</script>

Now, the server variable will be accessible to all Vue components via this.$root.API_URL (or $root.API_URL within Vue templates). It won't be available outside the Vue application.

Option 3: Sending data through the mounting point

// backend
<div id="app" 
   data-api-url="<%= backendVariable %>" 
   config='<%= jsonEncodedData %>' 
></div>

When attempting to add jsonEncodedData, single quotes should be used instead of double quotes.

// in your frontend 
new Vue({
   el: '#app',
   mounted() { 
       // This is how we access the externally provided data
       var API_URL = this.$el.getAttribute('data-api-url');

       // You have the option to make this value accessible to all consumers. 

       // Not limited to scalar values:
       try { 
          var CONFIG = JSON.parse(this.$el.getAttribute('config') || '{}');
       } catch (e) {
           console.error("Invalid json supplied to app: ", e);
           var CONFIG = { }; // default config
       }
   }
});

It's also feasible to use JSON.parse()

Option 4: Offering data through the mounting point template. We possess a JavaScript bundle that mounts the Vue app to #app.

// backend
// In this scenario, our mounting point includes a bare template as well
<div id="app">
   <app v-bind:config='<%= jsonEncodedData %>'></app>
   // or: 
   <app v-bind:config='{"api_url": "value"}'></app>
</div>
import App from './app.vue';
// frontend main
new Vue({
   el: '#app',
   components: { App }
});
// app.vue will receive our json encoded backend-data
// since we used v-bind:config, Vue will automatically parse the data
<script>
export default { 
    props: ['config']
}
</script>

Once again, feel free to expose this config data to the remainder of your application.

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

Important notice: It is not possible to assign refs to function components. Any attempt to do so will result in failure. If you intended to assign a ref, consider

My console is showing a warning when I use the nextJs Link component. Can someone assist me in resolving this issue and providing an explanation? Here is the message from the console: https://i.stack.imgur.com/jY4FA.png Below is a snippet of my code: im ...

Issues arise when attempting to incorporate the <style> tag in conjunction with requirejs and vue

I've been working on integrating a Vue app with an existing MVC application using require-js, require-vuejs, and vue-js. Everything was going smoothly until I encountered an error when trying to add a <style scoped> tag inside a component. If I ...

Ensure there is a gap between each object when they are arranged in a

Is there a way to customize the layout of elements in the ratings view so that there is automatic spacing between them? I considered using text (white spaces) for this purpose, but it seems like an inefficient solution. Are there any other alternatives to ...

How do you load a map with Vue.js Highmaps?

Recently, I started working with Vue.js and today I am experimenting with setting up a map to display data. After some research, I opted for Highmaps as it seemed like the most suitable option, especially because I have used Highcharts in previous projects ...

Creating a custom type in Typescript using a function for testing purposes

I have been exploring ways to limit my search capabilities to specific criteria. Let's say I have a model and some data like the following: interface UserModel { _id: string; username: string; party: UserPartyModel; } interface UserParty ...

Vue.js - sortable table with search functionality and image display

A Vue.js component/view I created displays data in the following format: <tbody v-for="item in items"> <tr> <td width="15%"><img :src="item.image"></td> <td width="50%">{{item.name}}</td> <td>{{item.purc ...

Retrieve information from Datatable Vuetify using axios fetch

I am encountering an issue with displaying data from a GET axios API. When inspecting the endpoint call, it correctly returns an array with objects. However, when attempting to display this data in the datatable, it shows that there is no data available. & ...

Getting a `undefined` value when changing templates in VueJS

Currently, I am transitioning a list to a table to enable more columns in the future, but I have encountered an undefined variable error that has left me confused. Below is the original list: <ul class="collection with-header"> ...

Styling headers in Vue, Vuetify table to appear bold

I am currently using Vue and Vuetify to create a table as needed. I would like to enhance the appearance of the headers by making them bold. my idea is to pass a class to the headers and customize them using CSS. However, even though I can see my custom cl ...

Oh no! A critical mistake has occurred: Mark-compact operations are not working efficiently near the heap limit, leading to a failed allocation due to the

My project is not particularly complex, I only just started it. However, when I run the command npm run dev, node js consumes more than 4GB of memory and eventually crashes with a fatal error: --- Last few GCs --- [16804:0000018EB02350F0] 128835 ms: Mar ...

An error occurred in Vuejs: Type Error - _vm.moment is not a recognized function

Encountering a challenge while attempting to migrate to moment on Vuejs. Upon executing npm install vue-moment and adding the following script: <script> const moment = require('vue-moment'); ... </script> I included this in my & ...

Establishing a Next.js API endpoint at the root level

I have a webpage located at URL root, which has been developed using React. Now, I am looking to create an API endpoint on the root as well. `http://localhost:3000/` > directs to the React page `http://localhost:3000/foo` > leads to the Next API end ...

Struggling to utilize a personalized filter leads to the error message: "Unable to call a function without a designated call signature."

Trying to use a custom filter from an Angular controller is resulting in the error message: 'Cannot invoke an expression whose type lacks a call signature'. I successfully implemented this on my last project, so I'm confused about what coul ...

What is the best way to retrieve a FireStore document ID from an object?

I'm in the process of trying to reference an auto-generated firestore document ID in order to create a subcollection within it. The issue I'm facing is that although I can locate the document ID, I'm struggling to save it to a variable in a ...

convert a JSON object into an array field

I am looking to convert a list of objects with the following structure: { "idActivite": 1, "nomActivite": "Accueil des participants autour d’un café viennoiseries", "descriptionActivite": "", "lieuActivite": "", "typeActivite": "", ...

Is it more important to focus on passing props or making API requests the top priority in your web application structure

Context Currently, I am working on a Vue App utilizing the Composition API. My backend serves as the source of data for loading pages and components. Inquiry When it comes to structuring my app's architecture, should I prioritize passing props thro ...

Should the utilization of vue-cli and vue-cli-service be considered an unsound practice?

As I develop an application using vue-cli, I've noticed that the webpack config is not explicitly defined in my repository. It seems to be hidden from us, although it can be adjusted if needed. The default run dev script by vue-cli also utilizes vue-c ...

Trouble rendering Bootstrap dropdown in Vue2 component

I am experiencing a peculiar issue with my Vue child component, which is responsible for displaying a bootstrap modal and includes several fields, including one that should show a dropdown selection. Strangely, the dropdown button fails to activate, result ...

Issue: Unable to link with 'dataSource' as it is not a recognized feature of 'mat-tree'

Upon following the example provided at https://material.angular.io/components/tree/overview, I encountered an error when trying to implement it as described. The specific error message is: Can't bind to 'dataSource' since it isn't a kn ...

I aim to conceal the Spinner feature within the service layer of Vue JS

I have a basic bootstrap Spinner.vue component <template> <div class="modal" v-if="start"> <div class="spinner-border text-info" role="status" style="width: 3rem; height: 3rem;" ...