Search code examples
javascriptvue.jsvuejs3primevue

Prevent tab change on PrimeVue TabView component


I am using the TabView component from PrimeVue (Vue 3), and I want to stop the tab change if any changes are made by the user, the problem is that I don't know how. I've already tried passing the event and using preventDefault and stopPropagation but seems that it doesn't work and click event is still happening.

The procedure should be:

  • If any changes are made, user press the tab and a dialog appears.

  • If user clicks 'No', I should prevent the tab change and stop the click event

Here is the demo of what I'm trying to archive, should be simple https://codesandbox.io/s/aged-wave-yzl1k?file=/src/App.vue:0-1753

If a flag is true I want to show a confirm dialog and prevent the tab change if user dismiss it.

The component that I'm using for the TabView: https://primefaces.org/primevue/showcase/#/tabview

Thanks in advance,


Solution

  • From the docs it looks like that internally the component will first switch tabs and then emit "tab-click", which explains the issue you're seeing. The exception is if the tab is disabled, in which case it won't change tabs but will emit "tab-click".

    It took a bit to figure out, but there is a way to get the functionality you need with only a small adjustment. It requires a change in your main.js as well as in your App.vue file.

    // main.js
    
    /*
     * Put this after you import TabView.
     * This will prevent automatic tab switching but still emits
     * the event to your application.
    */
    TabView.methods.onTabClick = function(event, tab, i) {
      this.$emit('tab-click', {
        originalEvent: event,
        tabInfo: tab,
        index: i
      });
    }
    
    // App.vue
    
    const onTabClick = (event) => {
      if (changes.value) {
        confirm.require({
          message:
            "Are you sure that you want to leave this tab? You'll lose your changes",
          icon: "fal fa-exclamation-triangle",
          acceptLabel: "Yes",
          rejectIcon: "No",
          accept: () => {
            alert("here we should allow tab change");
            activeIndex.value = event.index; // manually set activeIndex
          },
          reject: () => {
            alert("stop tab change");
          },
        });
      }
    };
    

    These changes modify what the onTabClick library method to only emit the event, without automatically switching. Then in your app you can check the index property of the event to determine what should be set to active.

    When implementing this solution, please be aware that it is not robust against changes to the underlying framework. If you do need a robust component, then you will have to implement a TabView yourself.