NAS-142225 / 27.0.0-BETA.1 / Fix Force checkbox not enabling Save on the NTP Server form - #13944
Conversation
…form Replaces the form-wide clearing from the first commit, which dropped pinned backend errors on any edit across all ix-form consumers. The clearing now lives on the NTP form's own `force` field and touches nothing else. Claude-Session: https://claude.ai/code/session_01PP236cd5LPtgSVz1aiL8pm
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #13944 +/- ##
=======================================
Coverage 88.51% 88.51%
=======================================
Files 1889 1890 +1
Lines 71294 71322 +28
Branches 9204 9209 +5
=======================================
+ Hits 63103 63129 +26
- Misses 8191 8193 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Four findings, all LOW. Nothing here blocks. ✅ The move from I traced the emission ordering for the claim in the doc comment on The findings, in full inline:
Focusing the native control inside the tn-* host is a real a11y improvement over |
Restores the error-modal escalation for a control that is nowhere in the DOM, replaces the side-effecting NTP validator with a declarative `clearsServerErrorsFor` hook on FormDefinition, gives the three manualValidateError keys one home, focuses the native control inside a tn-* host, and asserts the pinned message in the NTP spec. Claude-Session: https://claude.ai/code/session_015DNgeeCxxzRm7YJwr2uVvv
Replaces `clearsServerErrorsFor` with the same semantics applied by default. `FormErrorHandlerService` now owns retiring the pin it sets: a one-shot subscription on the control's root drops the verdict on the next edit anywhere in the form, by re-running the control's validators so its real validation state comes back. This covers every caller of `handleValidationErrors`, including legacy SidePanelForm hosts that `<ix-form>` can never reach, and needs no per-field declaration — nothing to remember, nothing to forget. Unsubscribing before the clearing lets `updateValueAndValidity()` emit normally, so `<ix-form>`'s status signal refreshes on its own and the manual `formStatus.set()` from the first attempt is not needed. Claude-Session: https://claude.ai/code/session_01PP236cd5LPtgSVz1aiL8pm
…eIn host The NTP spec provided a null SlideInRef so `<ix-form-renderer>` would fall back to its panel-only path. Master removed the legacy host (#13955) along with the token, so the import no longer resolves and the suite fails to run. The renderer no longer needs the provider at all. Claude-Session: https://claude.ai/code/session_01PP236cd5LPtgSVz1aiL8pm
|
This PR has been merged and conversations have been locked. |
Changes:
Adding an unreachable NTP server via the documented Force escape hatch was a dead
end: the backend's "Server could not be reached. Check 'Force' to continue regardless."
was pinned onto the
addresscontrol withsetErrors(), which — unlike a validatorresult — never re-evaluates. Angular drops such a pin when that control changes, but
an error the user is meant to answer from a different field has no way out, so the
form stayed invalid and Save stayed disabled. The only escape was retyping the Address.
Two fixes:
form-error-handler.service.ts— the pin now retires itself. Each backendverdict describes one submitted payload, and the next edit anywhere in the form moves
the payload on. So when the service pins an error it also subscribes one-shot to the
control's
root.valueChangesand, on the next edit, re-runs that control'svalidators. Re-validating rather than blanking is the point: the pinned set is
replaced by the control's real validation state, so a field that is genuinely
empty-but-required goes back to saying
requiredinstead of falling silently valid,and live client-side validators keep their say. If the verdict still stands, the next
save pins it again.
Putting this in the service rather than in
<ix-form>means it covers all 67 callersof
handleValidationErrors, including forms<ix-form>never wraps, and needs noper-field declaration — nothing to remember, nothing to forget. Unsubscribing before
the clearing lets
updateValueAndValidity()emit normally, which is what refreshes<ix-form>'s status signal and so the host's Save button.Behaviour change worth flagging: a pinned backend message now also disappears if
the user edits an unrelated field. That is deliberate — the verdict describes a
payload that no longer exists — and matches what the directory-services form already
does by hand in
clearFormControlErrors(). Validator-driven errors are untouched:image-validatorandfile-validatorreturnixManualValidateErrorfrom realvalidator functions, so they re-evaluate normally and never carry the
manualValidateErrorflag this keys on.form-error-handler.service.ts— a failed element lookup no longer escalates toan error modal. The service pins the message on the control (rendered inline by
tn-form-field) and then looks up the DOM element purely to scroll/focus it. Bothlookup strategies missed for tn-* forms —
IxFormServiceonly knowsix-*controls,which register via
RegisteredControlDirective, and[formControlName]is aproperty binding that leaves no attribute behind — so every
<ix-form-renderer>formshowed the message twice, inline and in a modal. The lookup now also matches the
data-control-namethe renderer already stamps on each control, so scroll and focuswork there too, and focus lands on the native control inside the tn-* host rather
than the host itself. The genuine fallback (no control found, nothing renderable
inline) still opens the modal.
The three
manualValidateErrorkeys also get one home inmanual-validate-error.constants.ts, instead of being re-spelled at each reader.Testing:
Automated —
ntp-servers.form-config.spec.tsdrives the reported path end to endthrough
<ix-form-renderer>with the realFormErrorHandlerService, so the error isgenuinely pinned by a rejected
system.ntpserver.create:Plus
form-error-handler.service.spec.tscovers the retiring directly: re-validation vsblanket-clearing, a sibling's live validator surviving, a nested control retired by an
edit in a sibling group, and re-pinning when the next save is rejected again — as well
as the message staying inline-only when the element is missing.
Manual — System → Advanced → NTP Servers → Add, Address
192.0.2.1(RFC 5737,never routable), Save. Expect the inline error and no error modal. Tick
Force → error clears and Save enables; saving adds the server. Untick Force and
save again → the error returns, confirming the verdict is retired, not suppressed.
Downstream