Update Render component to accept multiple items, closures, and default to rendering it to a component writer.

This commit is contained in:
Jesse Brault 2025-06-01 11:53:30 -05:00
parent 13f85325a1
commit df395da792
3 changed files with 42 additions and 11 deletions

View File

@ -1,26 +1,34 @@
package groowt.view.component.web.lib
import groowt.view.View
import groowt.view.component.runtime.DefaultComponentWriter
class Render extends DelegatingWebViewComponent {
private final Object item
private final Object items
Render(Map attr) {
item = Objects.requireNonNull(attr.item, "<Render> attribute 'item' must not be null.")
if (attr.item && attr.items) {
throw new IllegalArgumentException("<Render> cannot have both 'item' and 'items' attributes.")
}
this.items = attr.item ? [attr.item] : attr.items ?: []
}
@Override
protected View getDelegate() {
return { Writer w ->
if (item.respondsTo('renderTo', [Writer] as Class[])) {
item.renderTo(w)
} else if (item.respondsTo('render')) {
w << item.render()
items.each {
if (it instanceof Closure) {
it = it()
}
if (it.respondsTo('renderTo', [Writer] as Class[])) {
it.renderTo(w)
} else if (it.respondsTo('render')) {
w << it.render()
} else {
throw new IllegalArgumentException(
'<Render> must use an item which responds to either renderTo(Writer) or render().'
)
def cw = new DefaultComponentWriter(w, context.renderContext, context)
cw << it
}
}
}
}

View File

@ -1,6 +1,5 @@
package groowt.view.component.web.lib
import groowt.view.component.web.WebViewComponentContext
import groowt.view.component.web.WebViewComponentScope
import org.junit.jupiter.api.Test

View File

@ -1,5 +1,7 @@
package groowt.view.component.web.lib
import groowt.view.component.web.BaseWebViewComponent
import org.junit.jupiter.api.Test
class RenderTests extends AbstractWebViewComponentTests {
@ -20,6 +22,14 @@ class RenderTests extends AbstractWebViewComponentTests {
}
static final class Hello extends BaseWebViewComponent {
Hello() {
super('Hello, World!')
}
}
@Test
void renderToExample() {
doTest('''
@ -44,4 +54,18 @@ class RenderTests extends AbstractWebViewComponentTests {
)
}
@Test
void rendersComponent() {
doTest('<Render item={<RenderTests.Hello />} />', 'Hello, World!', context {
configureRootScope {
addWithNoArgConstructor(Hello)
}
})
}
@Test
void rendersItems() {
doTest('<Render items={[0, 1, 2]} />', '012')
}
}