Jacobs63 / vue3-tabs-component

Vue 3 tabs component
MIT License
96 stars 27 forks source link

Appending to URL screws up the vue router #20

Closed kcdrez closed 1 year ago

kcdrez commented 2 years ago

Because selecting a tab appends the element to the route, this screws up my whole routing system. I.e. my page is .../myPage and appending .../myPage#Tab1 doesnt exist so the whole thing breaks. This makes the component useless for my project.

Jacobs63 commented 2 years ago

Hello,

would you mind adding a code snippet, perhaps some screenshots of the expected behavior and the current behavior?

I've used the tabs component with Vue3 router on a couple of projects with no issues.

normann commented 2 years ago

yes, I have the same problem. One of my vue router's paths is /page1/page2/, where I use this Tabs component and I have two tabs here with "#new-customer" and "#existing customer" as the rendered "href" of each anchor element, so when landing on the first tab, the URL in the browser is https://www.mysite.com/page1/page2/or https://www.mysite.com/page1/page2/#new-customer, they are all fine initially, but when I clicked on "Existing Customer" tab, it redirects to https://www.mysite.com/#new-customer, i.e, it 'ate' /page1/page2/ segments from the URL, where https://www.mysite.com/#new-customeris just my home page with non existed anchor #new-customer

So the issue is it doesn't pick up the relative URL segments /page1/page2/ when changing the urlFragment (#hash)

Jacobs63 commented 2 years ago

Hello,

this is odd behavior, as appending a hash to the URL is not handled by the package, but by the browser, as the href of a link element is targetting the specific tab. That means it should not and cannot contain a full relative URL, as this is undesired an may have unknown sideffects (especially with vue-router).

Which browser are you using? This might be specific to a browser.

Maqsyo commented 1 year ago

I'm using following workaround

Tabs mixin:

import {Tabs, Tab} from 'vue3-tabs-component';

export default {
    components: {
        Tabs,
        Tab
    },
    data()
    {
        return {
            selectedTab: 'tab-1'
        };
    },
    computed: {
        tabOptions()
        {
            return {
                useUrlFragment: false,
                defaultTabHash: this.selectedTab
            };
        }
    },
    watch: {
        $route: {
            immediate: true,
            handler()
            {
                this.setActiveTabFromRoute();
            }
        }
    },
    methods: {
        setActiveTabFromRoute()
        {
            const {$route} = this;
            if (!$route.query?.tab) { return; }
            this.selectedTab = $route.query.tab;

            if (!this.$refs.tabs) { return; }
            this.$refs.tabs.selectTab(`#${$route.query.tab}`);
        },
        tabChanged(selectedTab)
        {
            const {$route} = this;

            this.$router.replace({
                name: $route.name,
                params: $route.params,
                query: {tab: selectedTab.tab.computedId}
            });

            this.selectedTab = selectedTab.tab.computedId;
        }
    }
};

Template

<tabs
    ref="tabs"
    :cache-lifetime="-1"
    :options="tabOptions"
    @changed="tabChanged"
>
    <tab name="tab-1">
        Tab-1
    </tab>
    <tab name="Tab-2">
        Tab-2
    </tab>
</tabs>

This would be better if vue-tabs would work with v-models

Jacobs63 commented 1 year ago

The likely cause is the Vue router being used in hash mode.

The packages then are in conflict when using hashes, so I'd advise turning off using url fragment via the useUrlFragment option.