This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch 
feature/WW-5695-html5-constraint-validation
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 510f31acbfedecdc4a361a2eccd5d0c92574c5d1
Author: Lukasz Lenart <[email protected]>
AuthorDate: Mon Aug 24 19:19:44 2026 +0200

    WW-5695 docs(validation): correct the UIBean hook point and control-type 
resolution
    
    Reading the code turned up two errors in the approved design.
    
    evaluateExtraParams() is the last statement of evaluateParams(), and that is
    where TextField sets attributes.type. The hook cannot sit next to the 
tagNames
    block as written, because at that point no text field has a resolved type 
and
    every one of them would look like OTHER. It moves to the end of the method.
    
    attributes.type is set by TextField and nothing else on the input path, so 
the
    control type cannot come from the attribute map alone. Adds a 
getControlType()
    component hook with four overrides; Checkbox, Radio, File and Hidden fall
    through to OTHER, which emits nothing and is correct for all four.
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
---
 ...026-08-24-html5-constraint-validation-design.md | 35 ++++++++++++++++++++--
 1 file changed, 32 insertions(+), 3 deletions(-)

diff --git 
a/docs/superpowers/specs/2026-08-24-html5-constraint-validation-design.md 
b/docs/superpowers/specs/2026-08-24-html5-constraint-validation-design.md
index 58ed7f93b..5f572b2dd 100644
--- a/docs/superpowers/specs/2026-08-24-html5-constraint-validation-design.md
+++ b/docs/superpowers/specs/2026-08-24-html5-constraint-validation-design.md
@@ -175,14 +175,43 @@ Defaults to `false` in `default.properties` for 7.4.0 and 
`true` for 8.0.0.
 Off by default matters: the `html5` theme shipped in 7.2.x, so emitting 
`required` on upgrade would start
 blocking submits on forms that render unchanged today. The 8.0.0 flip lands in 
a major with a migration entry.
 
+### Resolving the control type
+
+`attributes.type` is set by `TextField.evaluateExtraParams` 
(`TextField.java:91`) and by nothing else on the
+input path — `TextArea`, `Select`, `Checkbox`, `File`, `Hidden` and `Radio` 
have no `type` attribute at all.
+So the control type cannot be read from the attribute map alone; it needs a 
component-level hook:
+
+```java
+protected HtmlControlType getControlType();   // UIBean, returns OTHER
+```
+
+Overridden in four places, which is all that is needed:
+
+| Component | Returns |
+|---|---|
+| `UIBean` (base) | `OTHER` — supports nothing, so unknown controls emit no 
constraints |
+| `TextField` | `HtmlControlType.from(getAttributes().get("type"))`, 
defaulting to `TEXT` when absent, matching `text.ftl`'s 
`attributes.type!"text"` |
+| `Password` | `PASSWORD` — it extends `TextField` but its template hardcodes 
the type |
+| `TextArea` | `TEXTAREA` |
+| `Select` | `SELECT` |
+
+`Checkbox`, `Radio`, `File` and `Hidden` deliberately get no override. They 
fall through to `OTHER`, which
+emits nothing — the correct answer for all four. `ComboBox` extends 
`TextField` and correctly inherits `TEXT`.
+
 ### `UIBean` hook
 
-`UIBean.evaluateParams` already resolves `final Form form = 
findAncestor(Form.class)` and appends to
-`tagNames`. Immediately after that block, when the constant is on and a form 
was found:
+`UIBean.evaluateParams` resolves `final Form form = (Form) 
findAncestor(Form.class)` at `UIBean.java:824`
+and appends to `tagNames` just below it. **The hook cannot go there.** 
`evaluateExtraParams()` is the *last*
+statement of `evaluateParams()` (`UIBean.java:905`), and that is where 
`TextField` sets `attributes.type` —
+so at the `tagNames` block the control type is not yet resolved and every text 
field would look like `OTHER`.
+
+The hook therefore goes at the very end of `evaluateParams()`, after the 
`evaluateExtraParams()` call. The
+`form` local is declared at method scope and is still in scope there (the 
tooltip block below it already
+uses it). When the constant is on and a form was found:
 
 ```
 form.getFieldValidators(translatedName)
-  → provider.constraintsFor(validators, HtmlControlType.from(type))
+  → provider.constraintsFor(validators, getControlType())
   → addParameter("constraints", map)
 ```
 

Reply via email to