#Vue + Pinia + modal

46 messages · Page 1 of 1 (latest)

fiery sundial
#

Hi. I am trying to open a vue component in a new browserWindow when a user clicks a button. This works, but I had to create a new vue app which linked the pinia store from main.js to history.js. history.js open a view named History.vue. This means I have two html files. One index.html and one history.html. This works as expected, but as soon as I open the modal, Pinia store wont display the selectedId I got from home.vue. Its like the store is reset after I open the modal.

#
// main.js
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
    secondaryWindow.loadURL(`${process.env['ELECTRON_RENDERER_URL']}/history.html`)
  } else {
    mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
    secondaryWindow.loadFile(join(__dirname, '../renderer/history.html'))
  }

#
// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import router from './router'
import App from './App.vue'

export const app = createApp(App)
export const pinia = createPinia()

app.use(pinia).use(router).mount('#app')
#
// history.js
import { createApp } from 'vue'
import { pinia } from './main.js';
import History from '../src/views/History.vue'
import { useInboundStore } from './store/inboundStore.js'

const historyApp = createApp(History);

historyApp.use(pinia).mount('#history');
#
<!-- index.html -->
<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
    <title>Electron</title>
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self' http://localhost:8000; font-src 'self' https://fonts.gstatic.com/; style-src 'self' https://fonts.googleapis.com/ 'unsafe-inline';">
  </head>

  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>
#
<!-- history.html -->
<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
    <title>Electron</title>
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self' http://localhost:8000; font-src 'self' https://fonts.gstatic.com/; style-src 'self' https://fonts.googleapis.com/ 'unsafe-inline';">
  </head>

  <body>
    <div id="history"></div>
    <script type="module" src="/src/history.js"></script>
  </body>
</html>
#

Is this the wrong way of doing this or is there something I am doing wrong?

#

It feels a bit dumb to have two apps just for a modal, but I dont see any other way of doing this. I could create a modal as a vue component, but I want to use electron browserWindow

subtle otter
#

browser windows are separated from each other

#

if you want to have data from window a in window b you need to pass data

fiery sundial
#

Thanks for your response. Could you give me an example of how I could pass the data from inboundStore between the two apps/windows? I would think creating the store inside main.js and then passing it to history.js would be enough.

subtle otter
#

i dont know what inboundStore is

#

but if you what to pass data from window a to window b you need ipc

fiery sundial
#
// inboundStore.js
import { defineStore } from 'pinia'
import { ref } from 'vue'

const API_BASE_URL = 'http://localhost:8000';

export const useInboundStore = defineStore('inboundStore', {
  state: () => ({
    selectedInboundEntryId: ref(''),
    inboundDeclaration: [],
    inboundDeclarations: [],
    currency: [],
    currencyData: [],
    selectedCurrencyId: ref(''),
    officeData: [],
    tradingPartners: [],
    addPurchaseOrder: ref(false),
    logs: []
  }),
    async getInboundDeclarationById(declarationId) {
      try {
        const response = await fetch(
          `${API_BASE_URL}/inbound/get-declarations/${declarationId}`,
          {
            method: 'GET',
            headers: {
              'Content-Type': 'application/json'
            }
          }
        )
        if (response.status === 200) {
          this.inboundDeclaration = await response.json()
          this.selectedInboundEntryId = this.inboundDeclaration._id
        } else {
          const errorData = await response.json()
          console.log('Error fetching declarations:', errorData.error)
        }
      } catch (error) {
        console.log('Error fetching declarations:', error.message)
      }
    },
subtle otter
#

It give me nothing

fiery sundial
#

I am setting the selectedInboundEntry to this.inboundDeclaration._id before I go to History.vue.
in History.vue i am using this action to get the History data:

// inboundStore.js
async getLogsById(declarationId) {
      try {
        console.log(this.selectedInboundEntryId, "Entry ID")
        const response = await fetch(
          `${API_BASE_URL}/api/inbound/get-logs/${declarationId}`,
          {
            method: 'GET',
            headers: {
              'Content-Type': 'application/json'
            }
          }
        )
        if (response.status === 200) {
          this.logs = await response.json()
          console.log(this.logs)
        } else {
          const errorData = await response.json()
          console.log('Error fetching declarations:', errorData.error)
        }
      } catch (error) {
        console.log('Error fetching declarations:', error.message)
      }
    },

// History.vue
<script setup>
import { useInboundStore } from '../store/inboundStore.js'
import { storeToRefs } from 'pinia';
import { onMounted, watch } from 'vue';


const inboundStore = useInboundStore();
const { inboundDeclaration, logs, selectedInboundEntryId, inboundDeclarations, currencyData, officeData } = storeToRefs(inboundStore);

onMounted( async () => {
  await inboundStore.getLogsById(selectedInboundEntryId.value)
});
#

Sorry Discord dont allow me to paste everything :/

subtle otter
#

I don't know how pinia works

fiery sundial
#

Its like vuex if that helps

subtle otter
#

Are you able to sync data between 2 tabs in browser?

#

With pinia?

fiery sundial
#

I can sync data between the whole app. If i set this.selectedInboundEntryId in a component, it is persistent in whatever view or component I load the inboundStore

subtle otter
#

If i open your app in different tabs

#

Will it sync data?

#

Between then

fiery sundial
#

but as soon as I added another app the store is somehow reset. it doesnt even log undefined.

console.log(this.selectedInboundEntryId, "Entry ID")

// Logs Entry ID

subtle otter
#

Because every tab have its own store

fiery sundial
#

Yes. I belive so. I have not used tabs, I am using a vue router in the main app and everything is synced.

subtle otter
#

Vue router just add fake navigation into web page

#

Data stay the same

#

Something like this

fiery sundial
#

I might be both doing this the wrong way or overthinking the whole concept here, but electron-vite creates a main, preload and a renderer folder. Everything runs from the main.js inside the renderer. This means that all the parts in vue runs with a single .html file.
Every tutorial or docs I have seen online use different html files for different BrowserWindows. Thats what got me to where I am right now. Two Vue apps with two html files. This seems a bit like: "over comblicating things"

subtle otter
#

If you consider html file as separate app then yes

#

For me its another html file you can open in browser window

#

in SPA world you only have one html file

#

As entry point

#

And vue router show some parts of the app based on path or query

fiery sundial
#

Something like this would make sense to me, but this wont work xD.

if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
    secondaryWindow.loadURL(`${process.env['ELECTRON_RENDERER_URL']}/src/views/History.vue`)
  } else {
    mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
    secondaryWindow.loadFile(join(__dirname, '../renderer/src/views/History.vue'))
  }
#

Maybe I should not use Vue and go back to Vanilla and create everything separately.

subtle otter
#

Without navigation

#

Save thing happens with vanilla js

#

That's how browser works

#

You need to sync data between them

#

Or pass data to new window

fiery sundial
#

Thanks for all your help and patience yesterday. I tried to rewrite my project to Vanilla yesterday. It works as expected. I removed pinia store and used ipc to send the messages from the backend between windows. Now it works as expected.