diff --git a/htmlflow-core/src/main/java/htmlflow/HtmlPage.java b/htmlflow-core/src/main/java/htmlflow/HtmlPage.java
index baaafeb..55cd194 100644
--- a/htmlflow-core/src/main/java/htmlflow/HtmlPage.java
+++ b/htmlflow-core/src/main/java/htmlflow/HtmlPage.java
@@ -37,6 +37,7 @@
import org.xmlet.htmlapifaster.Element;
import org.xmlet.htmlapifaster.Html;
import org.xmlet.htmlapifaster.Span;
+import org.xmlet.htmlapifaster.Tbody;
import org.xmlet.htmlapifaster.Tr;
/**
@@ -90,6 +91,10 @@ public final Span span() {
return new Span<>(this);
}
+ public final Tbody tbody() {
+ return new Tbody<>(this);
+ }
+
/**
* Returns a new instance of HtmlFlow with the same properties of this object but with indented
* set to the value of isIndented parameter.
diff --git a/htmlflow-core/src/test/java/htmlflow/test/TestTable.java b/htmlflow-core/src/test/java/htmlflow/test/TestTable.java
index 99282d1..bca0ba4 100644
--- a/htmlflow-core/src/test/java/htmlflow/test/TestTable.java
+++ b/htmlflow-core/src/test/java/htmlflow/test/TestTable.java
@@ -25,6 +25,7 @@
import htmlflow.HtmlFlow;
import htmlflow.HtmlView;
+import htmlflow.test.model.Agent;
import htmlflow.test.model.Priority;
import htmlflow.test.model.Status;
import htmlflow.test.model.Task;
@@ -244,6 +245,20 @@ public void testTableWithPartialsBindingTwice() {
validateBindingTable(view.render(dataSource));
}
+ @Test
+ public void testRenderTableBody() {
+ List agents = Arrays.asList(
+ new Agent(1, "Agent Smith " + 1, "void"+ 1 +"@null.org"),
+ new Agent(2, "Agent Smith " + 2, "void"+ 2 +"@null.org"),
+ new Agent(3, "Agent Smith " + 3, "void"+ 3 +"@null.org")
+ );
+
+ String actualTableBody = HtmlTables.agentsTableBodyView.render(agents);
+
+ assertEquals(expectedTableBodyPartial, actualTableBody);
+
+ }
+
static void validateBindingTable(String actual){
Iterator iter = NEWLINE
.splitAsStream(actual)
@@ -311,4 +326,34 @@ private static void assertSimpleHtmlView(byte[] html, int[][] output) {
}
}
}
+
+ private final static String expectedTableBodyPartial =
+ """
+
+
+ |
+ Agent Smith 1
+ |
+
+ void1@null.org
+ |
+
+
+ |
+ Agent Smith 2
+ |
+
+ void2@null.org
+ |
+
+
+ |
+ Agent Smith 3
+ |
+
+ void3@null.org
+ |
+
+
+ """.trim();
}
diff --git a/htmlflow-core/src/test/java/htmlflow/test/model/Agent.java b/htmlflow-core/src/test/java/htmlflow/test/model/Agent.java
new file mode 100644
index 0000000..360662b
--- /dev/null
+++ b/htmlflow-core/src/test/java/htmlflow/test/model/Agent.java
@@ -0,0 +1,24 @@
+package htmlflow.test.model;
+
+public class Agent {
+ private final long id;
+ private final String name;
+ private final String email;
+
+ public Agent(long id, String name, String email) {
+ this.id = id;
+ this.name = name;
+ this.email = email;
+ }
+
+ public long getId() {
+ return id;
+ }
+ public String getName() {
+ return name;
+ }
+ public String getEmail() {
+ return email;
+ }
+
+}
diff --git a/htmlflow-core/src/test/java/htmlflow/test/views/HtmlTables.java b/htmlflow-core/src/test/java/htmlflow/test/views/HtmlTables.java
index 93fe588..1caad92 100644
--- a/htmlflow-core/src/test/java/htmlflow/test/views/HtmlTables.java
+++ b/htmlflow-core/src/test/java/htmlflow/test/views/HtmlTables.java
@@ -28,6 +28,7 @@
import htmlflow.HtmlPage;
import htmlflow.HtmlTemplate;
import htmlflow.HtmlView;
+import htmlflow.test.model.Agent;
import htmlflow.test.model.Task;
import org.xmlet.htmlapifaster.EnumRelType;
import org.xmlet.htmlapifaster.EnumTypeContentType;
@@ -201,4 +202,16 @@ public static void taskTableView(HtmlPage view){
.__() // body
.__() // html
);
+
+ public static HtmlView agentsTableBodyView = HtmlFlow.view(view -> view
+ .tbody()
+ .>dynamic((tbody, agents) -> agents.forEach(agent ->
+ tbody
+ .tr()
+ .td().text(agent.getName()).__()
+ .td().text(agent.getEmail()).__()
+ .__() // tr
+ ))
+ .__()
+ );
}
diff --git a/htmlflow-kotlin/src/main/kotlin/htmlflow/HtmlFlowExtensions.kt b/htmlflow-kotlin/src/main/kotlin/htmlflow/HtmlFlowExtensions.kt
index dbdc093..225d2fa 100644
--- a/htmlflow-kotlin/src/main/kotlin/htmlflow/HtmlFlowExtensions.kt
+++ b/htmlflow-kotlin/src/main/kotlin/htmlflow/HtmlFlowExtensions.kt
@@ -8,6 +8,7 @@ import org.xmlet.htmlapifaster.Div
import org.xmlet.htmlapifaster.Element
import org.xmlet.htmlapifaster.Html
import org.xmlet.htmlapifaster.Span
+import org.xmlet.htmlapifaster.Tbody
import org.xmlet.htmlapifaster.Text
import org.xmlet.htmlapifaster.Tr
@@ -31,6 +32,8 @@ inline fun HtmlPage.tr(block: Tr.() -> Unit): HtmlPage = this.tr().app
inline fun HtmlPage.span(block: Span.() -> Unit): HtmlPage = this.span().apply(block).l
+inline fun HtmlPage.tbody(block: Tbody.() -> Unit): HtmlPage = this.tbody().apply(block).l
+
/** Text node property. */
inline var , Z : Element<*, *>> T.text: T
get() = self()
diff --git a/htmlflow-kotlin/src/test/kotlin/htmlflow/test/TestKotlinExtensionsOnPartials.kt b/htmlflow-kotlin/src/test/kotlin/htmlflow/test/TestKotlinExtensionsOnPartials.kt
index 717f5e2..fcb5bf1 100644
--- a/htmlflow-kotlin/src/test/kotlin/htmlflow/test/TestKotlinExtensionsOnPartials.kt
+++ b/htmlflow-kotlin/src/test/kotlin/htmlflow/test/TestKotlinExtensionsOnPartials.kt
@@ -380,6 +380,52 @@ data class Agent(
}
data class Counter(val count: Int)
+ @Test
+ fun testThatTbodyElementCanBeUsedOnHtmlDocAndHtmlView(){
+ val agentsTableDoc =
+ StringBuilder()
+ .apply {
+ doc {
+ tbody {
+ tr {
+ td { text("James Bond") }
+ td { text("bond@mi6.gov.uk") }
+ td { text("007") }
+ }
+ tr {
+ td { text("Ethan Hunt") }
+ td { text("ehunt@imf.gov") }
+ td { text("001") }
+ }
+ }
+ }
+ }.toString()
+
+ assertEquals(expectedAgentsTableDoc, agentsTableDoc)
+
+ val agents = listOf(
+ Agent("Jason Bourne", "bourne@cia.gov", "002"),
+ Agent("Napoleon Solo", "solo@uncle.org", "003")
+ )
+
+ val agentsTableView =
+ view> {
+ tbody {
+ dyn { agents: List ->
+ agents.forEach { agent ->
+ tr {
+ td { text(agent.name) }
+ td { text(agent.email) }
+ td { text(agent.id) }
+ }
+ }
+ }
+ }
+ }.render(agents)
+
+ assertEquals(expectedAgentsTableView, agentsTableView)
+ }
+
}
private const val expectedFavoriteMoviesView =
@@ -463,4 +509,58 @@ private val expectedCounterSpans =
The counter 2 has the value 1
-"""
\ No newline at end of file
+"""
+
+
+private const val expectedAgentsTableDoc =
+ """
+
+
+ |
+ James Bond
+ |
+
+ bond@mi6.gov.uk
+ |
+
+ 007
+ |
+
+
+ |
+ Ethan Hunt
+ |
+
+ ehunt@imf.gov
+ |
+
+ 001
+ |
+
+"""
+
+private const val expectedAgentsTableView =
+ """
+
+ |
+ Jason Bourne
+ |
+
+ bourne@cia.gov
+ |
+
+ 002
+ |
+
+
+ |
+ Napoleon Solo
+ |
+
+ solo@uncle.org
+ |
+
+ 003
+ |
+
+"""
\ No newline at end of file