Summary
Public ui.Template APIs currently treat an empty outerHTMLTag as an unwrapped partial. An unwrapped Template has no single DOM node carrying its Element JID, so it cannot safely serve as a reusable or reconciled UI value. In particular, Container removal and ordering require each logical child to have one addressable direct DOM node.
No production or example call site in this repository uses $.Template with an empty wrapper. Existing occurrences are tests and benchmarks. Structural fragments that need no wrapper can use native html/template inclusion so the enclosing Template owns their DOM.
Make an empty public wrapper default to "div" and document that public Template values always have an addressable wrapper. Whole-page rendering remains unwrapped through the private pageTemplate path in ui.Handler.
Class / severity
API documentation / safe defaults — Low. The current API makes a lifecycle-invalid reusable value easy to construct, but ordinary callers already supply a wrapper.
Current behavior
tmpl := ui.NewTemplate("", "partial", dot)
// tmpl.OuterHTMLTag == "" and rendering emits no JID-owning wrapper.
RequestWriter.Template("", ...) has the same unwrapped behavior. The documentation also describes unwrapped Templates as Register updaters and discusses Template reuse in Containers without qualifying that children must be wrapped.
Intended behavior
tmpl := ui.NewTemplate("", "partial", dot)
// tmpl.OuterHTMLTag == "div"
RequestWriter.Template("", ...) should render the same generated div wrapper. Callers needing an unwrapped static/structural partial should use Go's native template action:
JaWS-managed partials should use their semantic root element as the wrapper, such as tr, td, li, or option.
Why this matters
Container reconciliation sends Remove and Order operations using each child Element's JID. An unwrapped Template emits no node with that JID, so browser removal/order cannot target its output even though the server removes or reorders the logical Element.
Defaulting public construction to div prevents that invalid state without introducing a constructor error or panic.
Acceptance criteria
Notes
Template has exported fields, so direct struct literals remain an escape hatch unless separately restricted. The public contract should direct callers through NewTemplate and state that reusable Template values require a non-empty wrapper.
Summary
Public
ui.TemplateAPIs currently treat an emptyouterHTMLTagas an unwrapped partial. An unwrapped Template has no single DOM node carrying its Element JID, so it cannot safely serve as a reusable or reconciled UI value. In particular, Container removal and ordering require each logical child to have one addressable direct DOM node.No production or example call site in this repository uses
$.Templatewith an empty wrapper. Existing occurrences are tests and benchmarks. Structural fragments that need no wrapper can use nativehtml/templateinclusion so the enclosing Template owns their DOM.Make an empty public wrapper default to
"div"and document that public Template values always have an addressable wrapper. Whole-page rendering remains unwrapped through the privatepageTemplatepath inui.Handler.Class / severity
API documentation / safe defaults — Low. The current API makes a lifecycle-invalid reusable value easy to construct, but ordinary callers already supply a wrapper.
Current behavior
RequestWriter.Template("", ...)has the same unwrapped behavior. The documentation also describes unwrapped Templates asRegisterupdaters and discusses Template reuse in Containers without qualifying that children must be wrapped.Intended behavior
RequestWriter.Template("", ...)should render the same generateddivwrapper. Callers needing an unwrapped static/structural partial should use Go's native template action:JaWS-managed partials should use their semantic root element as the wrapper, such as
tr,td,li, oroption.Why this matters
Container reconciliation sends
RemoveandOrderoperations using each child Element's JID. An unwrapped Template emits no node with that JID, so browser removal/order cannot target its output even though the server removes or reorders the logical Element.Defaulting public construction to
divprevents that invalid state without introducing a constructor error or panic.Acceptance criteria
NewTemplate("", name, dot)stores"div"asOuterHTMLTag.RequestWriter.Template("", name, dot, ...)renders a generateddivwrapper with the JaWS ID and wrapper attributes.ui.Handlercontinues to render whole-page templates without a generated wrapper through its private page-rendering path.{{template ...}}inclusion for unwrapped structural fragments.Registerupdater.lib/uitests, README, examples, and the JaWS skill to the same contract.NewTemplate("", ...)can remove and reorder its child normally.Notes
Templatehas exported fields, so direct struct literals remain an escape hatch unless separately restricted. The public contract should direct callers throughNewTemplateand state that reusable Template values require a non-empty wrapper.