-
-
Notifications
You must be signed in to change notification settings - Fork 284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature: add templ.HasChildren function #975
Comments
Good idea. I propose a design like this: func Children(ctx context.Context) (ok bool, c templ.Component) {
_, v := getContext(ctx)
if v.children == nil {
return false, NopComponent
}
return true, *v.children
} So you could use it as: if children, ok := templ.Children(ctx); ok {
@children
} else {
<div>No children</div>
} This wouldn't replace the To implement this, we'd need some generator tests to ensure that Happy to take a PR for this if someone else wants to implement, also happy to hear comments on the proposal, including naming the function something else. |
Acceptable, it looks like due to the early calculation of child components it would be logical to use a flag whether the child components were initially passed or not, because the order of the call would then matter. |
I'm not sure I completely follow. Are you suggesting a different API? We have an experimental package at https://github.com/templ-go/x - that might be a good place for a proof-of-concept design. |
How would you implement that in a templ List(){} like annotation? I heavily using this kind of structure as the docs are telling, but I didn't find anything on how to get from a code component to a templ component. |
@pulsone21 it would be used as follows: templ List() {
if children, ok := templ.Children(ctx); ok {
<ul>
@children
</ul>
} else {
<div>No children</div>
}
}
templ Page() {
@List() {
<li>A</li>
<li>B</li>
<li>C</li>
}
} |
I have implemented the suggested change into my fork, see here: The unit Tests are working, run However i have the issue that the generator test I struggle a bit to reverse engineer how this actually works, so i come to ask for some help. PS: Prior a eventual PR to the main i would squash everything and clean it up. |
Seems like a bug to me. I wouldn't expect the context is cleared after I get a value out of it. Since I see now the clear children call I wonder if this is why the in initial proposal returned also the children's not only a book. |
I have a proposal that I previously voiced - freezing the flag in terms of its initial state regarding the child elements. We are effectively freezing the variable storing the number of elements (someone might need to know this number), bypassing the cleanup of the child elements. I understand why cleaning is done so as not to confuse nested components, but it creates a problem with further work. Since code generation exists, why not use its capabilities? |
The information about child documents is being lost from the context before an attempt to retrieve it at the code level because code generation creates a precedent for clearing information about the presence of child elements. |
I just updated the The final template code would look like this: ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
if ok := templ.HasChildren(ctx); ok {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<ul>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs("No children")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `generator/test-has-children/template.templ`, Line: 9, Col: 20}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
ctx = templ.ClearChildren(ctx)
return templ_7745c5c3_Err In my local testing it worked so far: go test ./...
ok github.com/a-h/templ (cached)
? github.com/a-h/templ/cfg [no test files]
ok github.com/a-h/templ/benchmarks/templ (cached) [no tests to run]
ok github.com/a-h/templ/cmd/templ (cached)
ok github.com/a-h/templ/cmd/templ/fmtcmd (cached)
ok github.com/a-h/templ/cmd/templ/generatecmd (cached)
ok github.com/a-h/templ/cmd/templ/generatecmd/modcheck (cached)
? github.com/a-h/templ/cmd/templ/generatecmd/run/testprogram [no test files]
? github.com/a-h/templ/cmd/templ/generatecmd/sse [no test files]
ok github.com/a-h/templ/cmd/templ/generatecmd/proxy (cached)
ok github.com/a-h/templ/cmd/templ/generatecmd/run (cached)
ok github.com/a-h/templ/cmd/templ/generatecmd/symlink (cached)
ok github.com/a-h/templ/cmd/templ/generatecmd/test-eventhandler (cached)
ok github.com/a-h/templ/cmd/templ/generatecmd/testwatch (cached)
ok github.com/a-h/templ/cmd/templ/generatecmd/watcher (cached)
? github.com/a-h/templ/cmd/templ/infocmd [no test files]
? github.com/a-h/templ/cmd/templ/lspcmd/lspdiff [no test files]
? github.com/a-h/templ/cmd/templ/lspcmd/httpdebug [no test files]
? github.com/a-h/templ/cmd/templ/lspcmd/pls [no test files]
? github.com/a-h/templ/cmd/templ/sloghandler [no test files]
? github.com/a-h/templ/cmd/templ/testproject [no test files]
? github.com/a-h/templ/cmd/templ/visualize [no test files]
? github.com/a-h/templ/examples/content-security-policy [no test files]
? github.com/a-h/templ/examples/hello-world-ssr [no test files]
? github.com/a-h/templ/examples/hello-world-static [no test files]
? github.com/a-h/templ/generator/htmldiff [no test files]
? github.com/a-h/templ/examples/syntax-and-usage/components [no test files]
? github.com/a-h/templ/get-version [no test files]
? github.com/a-h/templ/storybook [no test files]
ok github.com/a-h/templ/cmd/templ/imports 3.368s
ok github.com/a-h/templ/cmd/templ/lspcmd (cached)
ok github.com/a-h/templ/cmd/templ/lspcmd/proxy (cached)
ok github.com/a-h/templ/cmd/templ/processor (cached)
ok github.com/a-h/templ/examples/blog (cached)
ok github.com/a-h/templ/generator (cached)
ok github.com/a-h/templ/generator/test-a-href (cached)
ok github.com/a-h/templ/generator/test-attribute-errors (cached)
ok github.com/a-h/templ/generator/test-attribute-escaping (cached)
ok github.com/a-h/templ/generator/test-call (cached)
ok github.com/a-h/templ/generator/test-cancelled-context (cached)
ok github.com/a-h/templ/generator/test-complex-attributes (cached)
ok github.com/a-h/templ/generator/test-constant-attribute-escaping (cached)
ok github.com/a-h/templ/generator/test-context (cached)
ok github.com/a-h/templ/generator/test-css-expression (cached)
ok github.com/a-h/templ/generator/test-css-middleware (cached)
ok github.com/a-h/templ/generator/test-css-usage (cached)
ok github.com/a-h/templ/generator/test-doctype (cached)
ok github.com/a-h/templ/generator/test-element-attributes (cached)
ok github.com/a-h/templ/generator/test-elseif (cached)
ok github.com/a-h/templ/generator/test-for (cached)
ok github.com/a-h/templ/generator/test-form-action (cached)
ok github.com/a-h/templ/generator/test-go-comments (cached)
ok github.com/a-h/templ/generator/test-go-template-in-templ (cached)
ok github.com/a-h/templ/generator/test-has-children (cached)
ok github.com/a-h/templ/generator/test-html (cached)
ok github.com/a-h/templ/generator/test-html-comment (cached)
ok github.com/a-h/templ/generator/test-if (cached)
ok github.com/a-h/templ/generator/test-ifelse (cached)
ok github.com/a-h/templ/generator/test-import (cached)
ok github.com/a-h/templ/generator/test-method (cached)
ok github.com/a-h/templ/generator/test-once (cached)
ok github.com/a-h/templ/generator/test-only-scripts (cached)
ok github.com/a-h/templ/generator/test-raw-elements (cached)
ok github.com/a-h/templ/generator/test-script-inline (cached)
ok github.com/a-h/templ/generator/test-script-usage (cached)
ok github.com/a-h/templ/generator/test-script-usage-nonce (cached)
ok github.com/a-h/templ/generator/test-spread-attributes (cached)
ok github.com/a-h/templ/generator/test-string (cached)
ok github.com/a-h/templ/generator/test-string-errors (cached)
ok github.com/a-h/templ/generator/test-switch (cached)
ok github.com/a-h/templ/generator/test-switchdefault (cached)
ok github.com/a-h/templ/generator/test-templ-element (cached)
ok github.com/a-h/templ/generator/test-templ-in-go-template (cached)
ok github.com/a-h/templ/generator/test-text (cached)
ok github.com/a-h/templ/generator/test-text-whitespace (cached)
ok github.com/a-h/templ/generator/test-void (cached)
ok github.com/a-h/templ/generator/test-whitespace-around-go-keywords (cached)
ok github.com/a-h/templ/parser/v2 (cached)
ok github.com/a-h/templ/parser/v2/goexpression (cached)
ok github.com/a-h/templ/runtime (cached)
ok github.com/a-h/templ/safehtml (cached)
ok github.com/a-h/templ/turbo (cached) But to be honest, i have no idea what are the possible implications of that change really are. |
Some components should have a default display if no child is passed, but the problem is that when calling
getChildren(ctx)
.But I get
NopComponent
. This is unacceptable because there is a nil check in the same function. I can't compare and understand whether there are child components or not.Please add the
HasChildren(ctx)
function to the release, which will give an understanding.So, i want to do like this one:
The text was updated successfully, but these errors were encountered: