about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorMarkus Wüstenberg2020-09-24 21:17:15 +0200
committerGitHub2020-09-24 21:17:15 +0200
commit5929ba8c41859ca9ea4117f42525e7be370ff55f (patch)
tree664af458ca56c8715f2fcbab6b84ddaf6a9a058f
parent4c109f9f1d4db4733d267ece171a533521029bdb (diff)
downloadgomponents-5929ba8c41859ca9ea4117f42525e7be370ff55f.tar.lz
gomponents-5929ba8c41859ca9ea4117f42525e7be370ff55f.tar.zst
gomponents-5929ba8c41859ca9ea4117f42525e7be370ff55f.zip
Add convenience helpers for form elements (#19)
-rw-r--r--attr/forms.go15
-rw-r--r--attr/forms_test.go16
-rw-r--r--el/elements.go10
-rw-r--r--el/forms.go52
-rw-r--r--el/forms_test.go58
5 files changed, 148 insertions, 3 deletions
diff --git a/attr/forms.go b/attr/forms.go
new file mode 100644
index 0000000..b3eec05
--- /dev/null
+++ b/attr/forms.go
@@ -0,0 +1,15 @@
+package attr
+
+import (
+	g "github.com/maragudk/gomponents"
+)
+
+// Placeholder returns an attribute with name "placeholder" and the given value.
+func Placeholder(v string) g.Node {
+	return g.Attr("placeholder", v)
+}
+
+// Required returns an attribute with name "required".
+func Required() g.Node {
+	return g.Attr("required")
+}
diff --git a/attr/forms_test.go b/attr/forms_test.go
new file mode 100644
index 0000000..3ff077b
--- /dev/null
+++ b/attr/forms_test.go
@@ -0,0 +1,16 @@
+package attr_test
+
+import (
+	"testing"
+
+	g "github.com/maragudk/gomponents"
+	"github.com/maragudk/gomponents/assert"
+	"github.com/maragudk/gomponents/attr"
+)
+
+func TestForms(t *testing.T) {
+	t.Run("adds placeholder and required attributes", func(t *testing.T) {
+		e := g.El("input", attr.Placeholder("hat"), attr.Required())
+		assert.Equal(t, `<input placeholder="hat" required/>`, e)
+	})
+}
diff --git a/el/elements.go b/el/elements.go
index 6745d1c..31bba14 100644
--- a/el/elements.go
+++ b/el/elements.go
@@ -121,9 +121,7 @@ func Em(text string, children ...g.Node) g.NodeFunc {
 }
 
 func Img(src, alt string, children ...g.Node) g.NodeFunc {
-	newChildren := prepend(g.Attr("alt", alt), children)
-	newChildren = prepend(g.Attr("src", src), newChildren)
-	return g.El("img", newChildren...)
+	return g.El("img", prepend2(g.Attr("src", src), g.Attr("alt", alt), children)...)
 }
 
 func prepend(node g.Node, nodes []g.Node) []g.Node {
@@ -131,3 +129,9 @@ func prepend(node g.Node, nodes []g.Node) []g.Node {
 	newNodes = append(newNodes, nodes...)
 	return newNodes
 }
+
+func prepend2(node1, node2 g.Node, nodes []g.Node) []g.Node {
+	newNodes := []g.Node{node1, node2}
+	newNodes = append(newNodes, nodes...)
+	return newNodes
+}
diff --git a/el/forms.go b/el/forms.go
new file mode 100644
index 0000000..9ada591
--- /dev/null
+++ b/el/forms.go
@@ -0,0 +1,52 @@
+package el
+
+import (
+	"fmt"
+
+	g "github.com/maragudk/gomponents"
+)
+
+// Button returns an element with name "button" and the given children.
+func Button(children ...g.Node) g.NodeFunc {
+	return g.El("button", children...)
+}
+
+// Form returns an element with name "form", the given action and method attributes, and the given children.
+func Form(action, method string, children ...g.Node) g.NodeFunc {
+	return g.El("form", prepend2(g.Attr("action", action), g.Attr("method", method), children)...)
+}
+
+// Input returns an element with name "input", the given type and name attributes, and the given children.
+// Note that "type" is a keyword in Go, so the parameter is called typ.
+func Input(typ, name string, children ...g.Node) g.NodeFunc {
+	return g.El("input", prepend2(g.Attr("type", typ), g.Attr("name", name), children)...)
+}
+
+// Label returns an element with name "label", the given for attribute, and the given children.
+// Note that "for" is a keyword in Go, so the parameter is called forr.
+func Label(forr string, children ...g.Node) g.NodeFunc {
+	return g.El("label", prepend(g.Attr("for", forr), children)...)
+}
+
+// Option returns an element with name "option", the given text content and value attribute, and the given children.
+func Option(text, value string, children ...g.Node) g.NodeFunc {
+	return g.El("option", prepend2(g.Attr("value", value), g.Text(text), children)...)
+}
+
+// Progress returns an element with name "progress", the given value and max attributes, and the given children.
+func Progress(value, max float64, children ...g.Node) g.NodeFunc {
+	return g.El("progress", prepend2(
+		g.Attr("value", fmt.Sprintf("%v", value)),
+		g.Attr("max", fmt.Sprintf("%v", max)),
+		children)...)
+}
+
+// Select returns an element with name "select", the given name attribute, and the given children.
+func Select(name string, children ...g.Node) g.NodeFunc {
+	return g.El("select", prepend(g.Attr("name", name), children)...)
+}
+
+// Textarea returns an element with name "textarea", the given name attribute, and the given children.
+func Textarea(name string, children ...g.Node) g.NodeFunc {
+	return g.El("textarea", prepend(g.Attr("name", name), children)...)
+}
diff --git a/el/forms_test.go b/el/forms_test.go
new file mode 100644
index 0000000..65f2fae
--- /dev/null
+++ b/el/forms_test.go
@@ -0,0 +1,58 @@
+package el_test
+
+import (
+	"testing"
+
+	g "github.com/maragudk/gomponents"
+	"github.com/maragudk/gomponents/assert"
+	"github.com/maragudk/gomponents/el"
+)
+
+func TestButton(t *testing.T) {
+	t.Run("returns a button element", func(t *testing.T) {
+		assert.Equal(t, `<button/>`, el.Button())
+	})
+}
+
+func TestForm(t *testing.T) {
+	t.Run("returns a form element with action and method attributes", func(t *testing.T) {
+		assert.Equal(t, `<form action="/" method="post"/>`, el.Form("/", "post"))
+	})
+}
+
+func TestInput(t *testing.T) {
+	t.Run("returns an input element with attributes type and name", func(t *testing.T) {
+		assert.Equal(t, `<input type="text" name="hat"/>`, el.Input("text", "hat"))
+	})
+}
+
+func TestLabel(t *testing.T) {
+	t.Run("returns a label element with attribute for", func(t *testing.T) {
+		assert.Equal(t, `<label for="hat">Hat</label>`, el.Label("hat", g.Text("Hat")))
+	})
+}
+
+func TestOption(t *testing.T) {
+	t.Run("returns an option element with attribute label and content", func(t *testing.T) {
+		assert.Equal(t, `<option value="hat">Hat</option>`, el.Option("Hat", "hat"))
+	})
+}
+
+func TestProgress(t *testing.T) {
+	t.Run("returns a progress element with attributes value and max", func(t *testing.T) {
+		assert.Equal(t, `<progress value="5.5" max="10"/>`, el.Progress(5.5, 10))
+	})
+}
+
+func TestSelect(t *testing.T) {
+	t.Run("returns a select element with attribute name", func(t *testing.T) {
+		assert.Equal(t, `<select name="hat"><option value="partyhat">Partyhat</option></select>`,
+			el.Select("hat", el.Option("Partyhat", "partyhat")))
+	})
+}
+
+func TestTextarea(t *testing.T) {
+	t.Run("returns a textarea element with attribute name", func(t *testing.T) {
+		assert.Equal(t, `<textarea name="hat"/>`, el.Textarea("hat"))
+	})
+}