Search code examples
vue.jselectronvuex

How to activate / deactivate an Electron.js submenu from inside a Vue.js Component according to a specific Vuex state?


I can't find the solution to this anywhere.

I have this sample vue-vuex-electron app that I've created and I want to enable / disable some submenus of the app according to whether the vuex state 'isLogged' is true or false. I managed to apply that to the nav router-links (using v-if), but not yet to the menu items... 'cause I don't know how to access the actual Menu (already set and rendered at the main process).

For example, at my Home.vue, I'd like to import the Electron.Menu of the app and set the following:

created(){
    if(this.$store.getters.isLogged){
        mainMenu.getMenuItemById('login').enabled = false
        mainMenu.getMenuItemById('logout').enabled = true
        mainMenu.getMenuItemById('currentWeather').enabled = true
    } else{
        mainMenu.getMenuItemById('login').enabled = true
        mainMenu.getMenuItemById('logout').enabled = false
        mainMenu.getMenuItemById('currentWeather').enabled = false
    }
}

But, when I try to import the Menu it's returned as undefined, not the menu already created and set to the app.

HOW CAN I HAVE ACCESS TO THE ACTUAL ELECTRON MENU FROM INSIDE A VUE INSTANCE IN ORDER TO CHANGE IT ?

The whole project is here: https://github.com/danielpm1982/open-weather-client

Thanks in advance ! :D

Daniel Pinheiro
danielpm1982.com
Brazil


Solution

  • OK, nobody knew this one, so I managed to work around it myself... and I'm sharing the solution to help others.

    I actually could not find a way to get or manage the Electron Menu at the renderer process, from within the Vue components, so I let it to be updated at the main process itself, where I have access to all Electron components easily.

    ipcMain.on('setMenuToLoggedInState', (e:Event, isLogged:boolean) => {
      const mainMenu: Menu = Menu.getApplicationMenu() as Menu
      if(isLogged){
        mainMenu.getMenuItemById('login').enabled = false
        mainMenu.getMenuItemById('logout').enabled = true
        mainMenu.getMenuItemById('currentWeather').enabled = true
      } else{
        mainMenu.getMenuItemById('login').enabled = true
        mainMenu.getMenuItemById('logout').enabled = false
        mainMenu.getMenuItemById('currentWeather').enabled = false
      }
    });

    Then, at the renderer side, or at the Home.vue component view, I simply emmit an event to the main process to notify it when the Vuex 'isLogged' state changes, that is, when I want it to update the Menu.

    computed: {
      ...mapGetters(['isLogged'])
    },
    created(){
      if(this.isLogged){
        ipcRenderer.send('setMenuToLoggedInState', true)
      } else{
        ipcRenderer.send('setMenuToLoggedInState', false)
      }
    }

    As, in the case of this app, both the Login as the Logout routes redirect to the Home View, the Home Vue component will always be able to check the 'isLogged' state at the Vuex store, on its creation, and notify the main process to update the Menu or subMenus according to that state.

    I don't know if there's a better way for this, but it works this way.

    I was avoiding to use ipcMain and ipcRenderer as much as I could, for not coupling the Vue components code with the Electron API, but in this case I had to use it.

    Now, my Menu submenus are activated and deactivated according to the user login state, as well as the router-links of the nav bar are generated or not according to that same state.

    Thanks to all those who might have tried to answer that.

    The whole project is here: https://github.com/danielpm1982/open-weather-client

    Daniel Pinheiro
    danielpm1982.com
    Brazil