diff --git a/packages/vue3/src/link.ts b/packages/vue3/src/link.ts index 49e5720bc..0edc62c36 100755 --- a/packages/vue3/src/link.ts +++ b/packages/vue3/src/link.ts @@ -36,6 +36,7 @@ export interface InertiaLinkProps { async?: boolean prefetch?: boolean | LinkPrefetchOption | LinkPrefetchOption[] cacheFor?: CacheForOption | CacheForOption[] + disabled?: boolean } type InertiaLink = DefineComponent @@ -132,6 +133,10 @@ const Link: InertiaLink = defineComponent({ type: Function as PropType<(cancelToken: import('axios').CancelTokenSource) => void>, default: () => {}, }, + disabled: { + type: Boolean, + default: false, + }, }, setup(props, { slots, attrs }) { const inFlightCount = ref(0) @@ -185,7 +190,7 @@ const Link: InertiaLink = defineComponent({ const elProps = { a: { href }, - button: { type: 'button' }, + button: { type: 'button', disabled: props.disabled }, } const baseParams = { @@ -219,14 +224,18 @@ const Link: InertiaLink = defineComponent({ } const prefetch = () => { - router.prefetch(href, baseParams, { cacheFor: cacheForValue }) + if (!props.disabled) { + router.prefetch(href, baseParams, { cacheFor: cacheForValue }) + } } const regularEvents = { onClick: (event) => { if (shouldIntercept(event)) { event.preventDefault() - router.visit(href, visitParams) + if (!props.disabled) { + router.visit(href, visitParams) + } } }, } @@ -252,7 +261,9 @@ const Link: InertiaLink = defineComponent({ }, onMouseup: (event) => { event.preventDefault() - router.visit(href, visitParams) + if (!props.disabled) { + router.visit(href, visitParams) + } }, onClick: (event) => { if (shouldIntercept(event)) { diff --git a/packages/vue3/test-app/Pages/Links/Disabled.vue b/packages/vue3/test-app/Pages/Links/Disabled.vue new file mode 100644 index 000000000..aabd47772 --- /dev/null +++ b/packages/vue3/test-app/Pages/Links/Disabled.vue @@ -0,0 +1,19 @@ + + + diff --git a/tests/app/server.js b/tests/app/server.js index 213ccca6c..fdb23a479 100644 --- a/tests/app/server.js +++ b/tests/app/server.js @@ -73,6 +73,8 @@ app.get('/links/headers/version', (req, res) => ) app.get('/links/data-loading', (req, res) => inertia.render(req, res, { component: 'Links/DataLoading' })) +app.get('/links/disabled', (req, res) => inertia.render(req, res, { component: 'Links/Disabled' })) + app.get('/visits/partial-reloads', (req, res) => inertia.render(req, res, { component: 'Visits/PartialReloads', diff --git a/tests/links.spec.ts b/tests/links.spec.ts index a45217788..9edd34112 100644 --- a/tests/links.spec.ts +++ b/tests/links.spec.ts @@ -754,3 +754,69 @@ test.describe('data-loading attribute', () => { await expect(link2).not.toHaveAttribute('data-loading') }) }) + +test.describe('disabled attribute', () => { + test('disables the link when the disabled attribute is set to true', async ({ page }) => { + await page.goto('/links/disabled') + const link = await page.getByRole('link', { name: 'Disabled', exact: true }) + await expect(link).not.toHaveAttribute('disabled') + await link.click() + await expect(page).toHaveURL('/links/disabled') + }) + + test('disables the link when the disabled attribute exists', async ({ page }) => { + await page.goto('/links/disabled') + const link = await page.getByRole('link', { name: 'Disabled Default', exact: true }) + await expect(link).not.toHaveAttribute('disabled') + await link.click() + await expect(page).toHaveURL('/links/disabled') + }) + + test('does not disable the link when the disabled attribute is set to false', async ({ page }) => { + await page.goto('/links/disabled') + const link = await page.getByRole('link', { name: 'Enabled', exact: true }) + await expect(link).not.toHaveAttribute('disabled') + await link.click() + await expect(page).toHaveURL('/links/disabled') + }) + + test('does not disable the link when the disabled attribute not exists', async ({ page }) => { + await page.goto('/links/disabled') + const link = await page.getByRole('link', { name: 'Enabled Default', exact: true }) + await expect(link).not.toHaveAttribute('disabled') + await link.click() + await expect(page).toHaveURL('/links/disabled') + }) + + test('disables the link (as=button) when the disabled attribute is set to true', async ({ page }) => { + await page.goto('/links/disabled') + const link = await page.getByRole('button', { name: 'Disabled Button', exact: true }) + await expect(link).toBeDisabled() + await expect(link).toHaveAttribute('disabled') + }) + + test('disables the link (as=button) when the disabled attribute is set', async ({ page }) => { + await page.goto('/links/disabled') + const link = await page.getByRole('button', { name: 'Disabled Default Button', exact: true }) + await expect(link).toBeDisabled() + await expect(link).toHaveAttribute('disabled') + }) + + test('does not disable the link (as=button) when the disabled attribute is set to false', async ({ page }) => { + await page.goto('/links/disabled') + const link = await page.getByRole('button', { name: 'Enabled Button', exact: true }) + await expect(link).not.toBeDisabled() + await expect(link).not.toHaveAttribute('disabled') + await link.click() + await expect(page).toHaveURL('/links/disabled') + }) + + test('does not disable the link (as=button) when the disabled attribute is not set', async ({ page }) => { + await page.goto('/links/disabled') + const link = await page.getByRole('button', { name: 'Enabled Default Button', exact: true }) + await expect(link).not.toBeDisabled() + await expect(link).not.toHaveAttribute('disabled') + await link.click() + await expect(page).toHaveURL('/links/disabled') + }) +})