diff --git a/element.go b/element.go index 00bc4d9..022f0b2 100644 --- a/element.go +++ b/element.go @@ -193,38 +193,13 @@ func (e *Element) Remove(htmlId string) { e.queue(what.Remove, htmlId) } -// ParseParams parses the parameters passed to UI() when creating a new Element, -// setting event handlers and returning a list of HTML attributes. -func (e *Element) ParseParams(params []any) (attrs []template.HTMLAttr) { +// ApplyParams parses the parameters passed to UI() when creating a new Element, +// adding UI tags, setting event handlers and returning a list of HTML attributes. +func (e *Element) ApplyParams(params []any) []template.HTMLAttr { + tags, handlers, attrs := ParseParams(params) if !e.deleted { - for i := range params { - switch data := params[i].(type) { - case template.HTMLAttr: - attrs = append(attrs, data) - case []template.HTMLAttr: - attrs = append(attrs, data...) - case string: - attr := template.HTMLAttr(data) // #nosec G203 - attrs = append(attrs, attr) - case []string: - for _, s := range data { - attr := template.HTMLAttr(s) // #nosec G203 - attrs = append(attrs, attr) - } - case EventFn: - if data != nil { - e.handlers = append(e.handlers, eventFnWrapper{data}) - } - default: - if h, ok := data.(ClickHandler); ok { - e.handlers = append(e.handlers, clickHandlerWapper{h}) - } - if h, ok := data.(EventHandler); ok { - e.handlers = append(e.handlers, h) - } - e.Tag(data) - } - } + e.handlers = append(e.handlers, handlers...) + e.Tag(tags...) } - return + return attrs } diff --git a/parseparams.go b/parseparams.go new file mode 100644 index 0000000..6cc54a8 --- /dev/null +++ b/parseparams.go @@ -0,0 +1,37 @@ +package jaws + +import "html/template" + +// ParseParams parses the parameters passed to UI() when creating a new Element, +// returning UI tags, event handlers and HTML attributes. +func ParseParams(params []any) (tags []any, handlers []EventHandler, attrs []template.HTMLAttr) { + for i := range params { + switch data := params[i].(type) { + case template.HTMLAttr: + attrs = append(attrs, data) + case []template.HTMLAttr: + attrs = append(attrs, data...) + case string: + attr := template.HTMLAttr(data) // #nosec G203 + attrs = append(attrs, attr) + case []string: + for _, s := range data { + attr := template.HTMLAttr(s) // #nosec G203 + attrs = append(attrs, attr) + } + case EventFn: + if data != nil { + handlers = append(handlers, eventFnWrapper{data}) + } + default: + if h, ok := data.(ClickHandler); ok { + handlers = append(handlers, clickHandlerWapper{h}) + } + if h, ok := data.(EventHandler); ok { + handlers = append(handlers, h) + } + tags = append(tags, data) + } + } + return +} diff --git a/request.go b/request.go index 4c14fcb..20123d9 100644 --- a/request.go +++ b/request.go @@ -289,7 +289,7 @@ func (rq *Request) Register(tagitem any, params ...any) jid.Jid { case jid.Jid: if elem := rq.getElementByJid(data); elem != nil { if _, ok := elem.Ui().(*UiHtml); ok { - elem.ParseParams(params) + elem.ApplyParams(params) } } return data @@ -300,7 +300,7 @@ func (rq *Request) Register(tagitem any, params ...any) jid.Jid { uib := &UiHtml{} elem := rq.NewElement(uib) uib.parseGetter(elem, tagitem) - elem.ParseParams(params) + elem.ApplyParams(params) return elem.Jid() } diff --git a/template.go b/template.go index 5fcd752..1cacceb 100644 --- a/template.go +++ b/template.go @@ -44,7 +44,7 @@ func (t Template) JawsRender(e *Element, w io.Writer, params []any) error { e.Request.tagExpanded(e, expandedtags) } var sb strings.Builder - for _, s := range e.ParseParams(params) { + for _, s := range e.ApplyParams(params) { sb.WriteByte(' ') sb.WriteString(string(s)) } diff --git a/uihtmlinner.go b/uihtmlinner.go index cc0c5d3..6014e88 100644 --- a/uihtmlinner.go +++ b/uihtmlinner.go @@ -11,7 +11,7 @@ type UiHtmlInner struct { func (ui *UiHtmlInner) renderInner(e *Element, w io.Writer, htmltag, htmltype string, params []any) error { ui.parseGetter(e, ui.HtmlGetter) - return WriteHtmlInner(w, e.Jid(), htmltag, htmltype, ui.JawsGetHtml(e), e.ParseParams(params)...) + return WriteHtmlInner(w, e.Jid(), htmltag, htmltype, ui.JawsGetHtml(e), e.ApplyParams(params)...) } func (ui *UiHtmlInner) JawsUpdate(e *Element) { diff --git a/uiimg.go b/uiimg.go index 8ae410f..6974a4e 100644 --- a/uiimg.go +++ b/uiimg.go @@ -14,7 +14,7 @@ type UiImg struct { func (ui *UiImg) JawsRender(e *Element, w io.Writer, params []any) error { ui.parseGetter(e, ui.StringGetter) srcattr := template.HTMLAttr("src=" + strconv.Quote(ui.JawsGetString(e))) // #nosec G203 - attrs := append(e.ParseParams(params), srcattr) + attrs := append(e.ApplyParams(params), srcattr) return WriteHtmlInner(w, e.Jid(), "img", "", "", attrs...) } diff --git a/uiinputbool.go b/uiinputbool.go index 10dcb0b..62d758f 100644 --- a/uiinputbool.go +++ b/uiinputbool.go @@ -14,7 +14,7 @@ type UiInputBool struct { func (ui *UiInputBool) renderBoolInput(e *Element, w io.Writer, htmltype string, params ...any) error { ui.parseGetter(e, ui.BoolSetter) - attrs := e.ParseParams(params) + attrs := e.ApplyParams(params) v := ui.JawsGetBool(e) ui.Last.Store(v) if v { diff --git a/uiinputdate.go b/uiinputdate.go index 574150a..b542e6c 100644 --- a/uiinputdate.go +++ b/uiinputdate.go @@ -18,7 +18,7 @@ func (ui *UiInputDate) str() string { func (ui *UiInputDate) renderDateInput(e *Element, w io.Writer, htmltype string, params ...any) error { ui.parseGetter(e, ui.TimeSetter) - attrs := e.ParseParams(params) + attrs := e.ApplyParams(params) ui.Last.Store(ui.JawsGetTime(e)) return WriteHtmlInput(w, e.Jid(), htmltype, ui.str(), attrs) } diff --git a/uiinputfloat.go b/uiinputfloat.go index c267df9..df7c6e9 100644 --- a/uiinputfloat.go +++ b/uiinputfloat.go @@ -18,7 +18,7 @@ func (ui *UiInputFloat) str() string { func (ui *UiInputFloat) renderFloatInput(e *Element, w io.Writer, htmltype string, params ...any) error { ui.parseGetter(e, ui.FloatSetter) - attrs := e.ParseParams(params) + attrs := e.ApplyParams(params) ui.Last.Store(ui.JawsGetFloat(e)) return WriteHtmlInput(w, e.Jid(), htmltype, ui.str(), attrs) } diff --git a/uiinputtext.go b/uiinputtext.go index 954c5bb..a98016a 100644 --- a/uiinputtext.go +++ b/uiinputtext.go @@ -13,7 +13,7 @@ type UiInputText struct { func (ui *UiInputText) renderStringInput(e *Element, w io.Writer, htmltype string, params ...any) error { ui.parseGetter(e, ui.StringSetter) - attrs := e.ParseParams(params) + attrs := e.ApplyParams(params) v := ui.JawsGetString(e) ui.Last.Store(v) return WriteHtmlInput(w, e.Jid(), htmltype, v, attrs) diff --git a/uioption.go b/uioption.go index d9af520..2eaacdb 100644 --- a/uioption.go +++ b/uioption.go @@ -10,7 +10,7 @@ type UiOption struct{ *NamedBool } func (ui UiOption) JawsRender(e *Element, w io.Writer, params []any) error { e.Tag(ui.NamedBool) - attrs := e.ParseParams(params) + attrs := e.ApplyParams(params) valattr := template.HTMLAttr(`value="` + html.EscapeString(ui.JawsGetString(e)) + `"`) // #nosec G203 attrs = append(attrs, valattr) if ui.Checked() { diff --git a/uitemplate.go b/uitemplate.go index 79dd8ea..4d9eae7 100644 --- a/uitemplate.go +++ b/uitemplate.go @@ -13,6 +13,9 @@ func NewUiTemplate(t Template) UiTemplate { // // The templ argument can either be a string, in which case Jaws.Template.Lookup() will // be used to resolve it. Or it can be a *template.Template directly. +// +// Note that templates are only rendered once; adding UI tags to a template +// have no effect, since JawsUpdate is a no-op for them. func (rq RequestWriter) Template(templ, dot any, params ...any) error { return rq.UI(NewUiTemplate(rq.rq.MakeTemplate(templ, dot)), params...) } diff --git a/uitextarea.go b/uitextarea.go index acd67f3..d7cda82 100644 --- a/uitextarea.go +++ b/uitextarea.go @@ -11,7 +11,7 @@ type UiTextarea struct { func (ui *UiTextarea) JawsRender(e *Element, w io.Writer, params []any) error { ui.parseGetter(e, ui.StringSetter) - attrs := e.ParseParams(params) + attrs := e.ApplyParams(params) return WriteHtmlInner(w, e.Jid(), "textarea", "", template.HTML(ui.JawsGetString(e)), attrs...) // #nosec G203 } diff --git a/uiwrapcontainer.go b/uiwrapcontainer.go index b7cde2c..a5f2d44 100644 --- a/uiwrapcontainer.go +++ b/uiwrapcontainer.go @@ -18,7 +18,7 @@ type uiWrapContainer struct { func (ui *uiWrapContainer) renderContainer(e *Element, w io.Writer, outerhtmltag string, params []any) (err error) { ui.parseGetter(e, ui.Container) - attrs := e.ParseParams(params) + attrs := e.ApplyParams(params) b := e.Jid().AppendStartTagAttr(nil, outerhtmltag) for _, attr := range attrs { b = append(b, ' ')