Skip to content

fix(ui): NcButton native-type is inert on @nextcloud/vue 9 — six forms never submitted - #430

Merged
rubenvdlinde merged 1 commit into
developmentfrom
fix/ncbutton-native-type-v9
Aug 4, 2026
Merged

fix(ui): NcButton native-type is inert on @nextcloud/vue 9 — six forms never submitted#430
rubenvdlinde merged 1 commit into
developmentfrom
fix/ncbutton-native-type-v9

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

The defect

@nextcloud/vue 9 renamed NcButton's visual prop typevariant and repurposed type as the native button type, with default: "button". nativeType was removed outright — it was the v8 name.

So native-type="submit" on v9 is an undeclared prop: it falls through to the DOM as an inert attribute while the button keeps type="button". A type="button" inside a <form> raises no submit event, so @submit.prevent never runs.

No console warning, no lint error, no failed request. User-facing: someone fills in a purchase order, clicks Create purchase order, sees no error, and nothing was ever sent.

This repo is on @nextcloud/vue ^9.9.0, lockfile-resolved to 9.9.0 — checked in the lockfile, not the caret.

The six sites

Every one already used variant= (the v9 visual prop), so these were half-finished v8→v9 migrations where only the button type was missed. Each verified per-site to sit inside a form with a submit handler — not blanket-rewritten:

site enclosing form
src/components/goods-receipt-note/GoodsReceiptNoteForm.vue:152 <form @submit.prevent="onSubmit">
src/components/purchase-order/PurchaseOrderForm.vue:160 <form @submit.prevent="onSubmit">
src/views/DeadlineCalendarSettings.vue:57 <form @submit.prevent="save">
src/views/bookings/BookingForm.vue:63 <form @submit.prevent="submit">
src/views/settings/PipelinqIntegration.vue:38 <form @submit.prevent="save">
src/views/settings/Settings.vue:21 <form @submit.prevent="save">

Each is native-type="submit"type="submit"; the diff is exactly 6 changed lines in 6 files. git grep native-type -- src now returns nothing.

Evidence

Behaviour is proven in ConductionNL/openconnector#1140, which mounts the real NcButton from the installed 9.9.0 and asserts DOM behaviour, with negative controls:

spelling renders submit handler
type="submit" (the fix) type=submit fires
native-type="submit" (the bug) type=button never fires

That test is mutation-checked: flipping the fix assertion back to the broken spelling makes it fail, so the assertion is shown capable of failing rather than merely passing.

The component-level mechanism is shared by all six sites here. What is verified by reading rather than execution is that each of these specific forms wraps its button — the table above — which is why every site was confirmed individually.

Coordination note

Peer agents were reported to have fixed some of these files earlier. At the time this branch was cut, all six were still present on origin/development and no remote branch had them fixed, so all six are included here. If a peer PR lands first, this rebases down to whatever remains rather than conflicting on content.

🤖 Generated with Claude Code

…rms never submitted

`@nextcloud/vue` 9 renamed NcButton's visual prop `type` -> `variant` and
repurposed `type` as the NATIVE button type, with `default: "button"`.
`nativeType` was removed outright — it was the v8 name.

`native-type="submit"` is therefore an undeclared prop on v9: it falls
through to the DOM as an inert attribute while the button keeps
`type="button"`. A `type="button"` inside a <form> raises no submit event,
so `@submit.prevent` never runs. No console warning, no lint error, no
failed request — a user fills in a purchase order, clicks Create, sees no
error, and nothing was ever sent.

All six sites already used `variant=` (the v9 visual prop), so these were
half-finished v8 -> v9 migrations where only the button type was missed.
Each verified to sit inside a form with a submit handler:

  goods-receipt-note/GoodsReceiptNoteForm.vue:152  <form @submit.prevent="onSubmit">
  purchase-order/PurchaseOrderForm.vue:160         <form @submit.prevent="onSubmit">
  views/DeadlineCalendarSettings.vue:57            <form @submit.prevent="save">
  views/bookings/BookingForm.vue:63                <form @submit.prevent="submit">
  views/settings/PipelinqIntegration.vue:38        <form @submit.prevent="save">
  views/settings/Settings.vue:21                   <form @submit.prevent="save">

Behaviour is proven in openconnector#1140, which mounts the real NcButton
9.9.0 and asserts that `type="submit"` fires the form's submit handler
while `native-type="submit"` fires nothing.
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/shillinq @ 1d1b275

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
composer ✅ 100/100
npm ✅ 547/547
PHPUnit
Newman
Playwright ⏭️

Quality workflow — 2026-08-04 10:18 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde

Copy link
Copy Markdown
Contributor Author

Merging with --admin. Failure set is identical to the base, compared against the last completed run rather than an in-flight one:

run failing
this PR latest Integration Tests (Newman), Quality Report
development 30896861325 (31 jobs) same two

Quality Report is red only because Newman is. Newman is pre-existing test debt and is being worked separately; this PR adds no new failure.

⚠️ Method note, since it bit me twice today: a run with a blank conclusion is still running, not passing. Reading an in-flight base as "no failures" would have made this PR look like it introduced two — I compared against the last completed verdict instead.

@rubenvdlinde
rubenvdlinde merged commit 7820723 into development Aug 4, 2026
34 of 36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant