Skip to content

Commit

Permalink
Merge pull request #6 from chasefleming/chasefleming/form-elements
Browse files Browse the repository at this point in the history
Add Missing Form Elements
  • Loading branch information
chasefleming authored Oct 8, 2023
2 parents 31b37bb + e5e6355 commit e530f38
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 25 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,20 +98,26 @@ In this example, if `isAdmin` is `true`, the `Admin Panel` link is rendered. Oth
- `Code`: Code `<code>`
- `Div`: Division `<div>`
- `Em`: Emphasis `<em>`
- `Form`: Form `<form>`
- `H1`: Heading 1 `<h1>`
- `H2`: Heading 2 `<h2>`
- `H3`: Heading 3 `<h3>`
- `Head`: Head `<head>`
- `Html`: HTML `<html>`
- `Hr`: Horizontal Rule `<hr>`
- `Img`: Image `<img>`
- `Input`: Input `<input>`
- `Label`: Label `<label>`
- `Li`: List Item `<li>`
- `Meta`: Meta `<meta>`
- `Option`: Dropdown option `<option>`
- `P`: Paragraph `<p>`
- `Pre`: Preformatted Text `<pre>`
- `Script`: Script `<script>`
- `Select`: Dropdown select `<select>`
- `Span`: Span `<span>`
- `Strong`: Strong `<strong>`
- `Textarea`: Textarea `<textarea>`
- `Title`: Title `<title>`
- `Ul`: Unordered List `<ul>`

Expand Down
55 changes: 30 additions & 25 deletions attrs/attrs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ package attrs

const (
// Universal Attributes
Alt = "alt"
Class = "class"
Dir = "dir" // Direction, e.g., "ltr" or "rtl"
ID = "id"
Lang = "lang"
Style = "style"
Tabindex = "tabindex"
Title = "title"
Alt = "alt"
Class = "class"
Contenteditable = "contenteditable"
Dir = "dir" // Direction, e.g., "ltr" or "rtl"
ID = "id"
Lang = "lang"
Style = "style"
Tabindex = "tabindex"
Title = "title"

// Link/Script Attributes
Async = "async"
Expand All @@ -31,23 +32,27 @@ const (
Width = "width"

// Form/Input Attributes
Accept = "accept"
Action = "action"
Autofocus = "autofocus"
Checked = "checked"
Disabled = "disabled"
For = "for" // Used with label elements
Max = "max"
MaxLength = "maxlength"
Method = "method" // e.g., "GET", "POST"
Min = "min"
Multiple = "multiple"
Name = "name"
Placeholder = "placeholder"
Readonly = "readonly"
Required = "required"
Type = "type"
Value = "value"
Accept = "accept"
Action = "action"
Autocapitalize = "autocapitalize"
Autocomplete = "autocomplete"
Autofocus = "autofocus"
Cols = "cols"
Checked = "checked"
Disabled = "disabled"
For = "for" // Used with label elements
Max = "max"
MaxLength = "maxlength"
Method = "method" // e.g., "GET", "POST"
Min = "min"
Multiple = "multiple"
Name = "name"
Placeholder = "placeholder"
Readonly = "readonly"
Required = "required"
Rows = "rows"
Type = "type"
Value = "value"

// Miscellaneous Attributes
DataPrefix = "data-" // Used for custom data attributes e.g., "data-custom"
Expand Down
24 changes: 24 additions & 0 deletions elements.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,30 @@ func Button(props Attrs, children ...interface{}) *Element {
return NewElement("button", props, children...)
}

func Form(attrs Attrs, children ...interface{}) *Element {
return NewElement("form", attrs, children...)
}

func Input(attrs Attrs) *Element {
return NewElement("input", attrs)
}

func Label(attrs Attrs, children ...interface{}) *Element {
return NewElement("label", attrs, children...)
}

func Option(attrs Attrs, content string) *Element {
return NewElement("option", attrs, content)
}

func Select(attrs Attrs, children ...interface{}) *Element {
return NewElement("select", attrs, children...)
}

func Textarea(attrs Attrs, content string) *Element {
return NewElement("textarea", attrs, content)
}

// ========== Hyperlinks and Multimedia ==========

func Img(props Attrs) *Element {
Expand Down
30 changes: 30 additions & 0 deletions elements_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,36 @@ func TestButton(t *testing.T) {
assert.Equal(t, expected, el.Render())
}

func TestForm(t *testing.T) {
expected := `<form action="/submit" method="post"><input name="username" type="text"></form>`
el := Form(Attrs{attrs.Action: "/submit", attrs.Method: "post"}, Input(Attrs{attrs.Type: "text", attrs.Name: "username"}))
assert.Equal(t, expected, el.Render())
}

func TestInput(t *testing.T) {
expected := `<input name="username" placeholder="Enter your username" type="text">`
el := Input(Attrs{attrs.Type: "text", attrs.Name: "username", attrs.Placeholder: "Enter your username"})
assert.Equal(t, expected, el.Render())
}

func TestLabel(t *testing.T) {
expected := `<label for="username">Username</label>`
el := Label(Attrs{attrs.For: "username"}, "Username")
assert.Equal(t, expected, el.Render())
}

func TestSelectAndOption(t *testing.T) {
expected := `<select name="color"><option value="red">Red</option><option value="blue">Blue</option></select>`
el := Select(Attrs{attrs.Name: "color"}, Option(Attrs{attrs.Value: "red"}, "Red"), Option(Attrs{attrs.Value: "blue"}, "Blue"))
assert.Equal(t, expected, el.Render())
}

func TestTextarea(t *testing.T) {
expected := `<textarea name="comment" rows="5">Leave a comment...</textarea>`
el := Textarea(Attrs{attrs.Name: "comment", attrs.Rows: "5"}, "Leave a comment...")
assert.Equal(t, expected, el.Render())
}

// ========== Hyperlinks and Multimedia ==========

func TestImg(t *testing.T) {
Expand Down
21 changes: 21 additions & 0 deletions examples/htmx-fiber-form/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module htmx-fiber-counter

go 1.21.1

require (
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/chasefleming/elem-go v0.2.0 // indirect
github.com/gofiber/fiber/v2 v2.49.2 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.49.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/sys v0.12.0 // indirect
)

replace github.com/chasefleming/elem-go => ../../../elem-go
29 changes: 29 additions & 0 deletions examples/htmx-fiber-form/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/chasefleming/elem-go v0.2.0 h1:rY/eoGpctBhiPoLYEcBb4ArvR0/nRyvM/XgvhW9r/cA=
github.com/chasefleming/elem-go v0.2.0/go.mod h1:hz73qILBIKnTgOujnSMtEj20/epI+f6vg71RUilJAA4=
github.com/gofiber/fiber/v2 v2.49.2 h1:ONEN3/Vc+dUCxxDgZZwpqvhISgHqb+bu+isBiEyKEQs=
github.com/gofiber/fiber/v2 v2.49.2/go.mod h1:gNsKnyrmfEWFpJxQAV0qvW6l70K1dZGno12oLtukcts=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.49.0 h1:9FdvCpmxB74LH4dPb7IJ1cOSsluR07XG3I1txXWwJpE=
github.com/valyala/fasthttp v1.49.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
78 changes: 78 additions & 0 deletions examples/htmx-fiber-form/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package main

import (
"fmt"
"github.com/chasefleming/elem-go"
"github.com/chasefleming/elem-go/attrs"
"github.com/chasefleming/elem-go/htmx"
"github.com/gofiber/fiber/v2"
)

func main() {
app := fiber.New()

// Define a simple structure to hold our form data
var formData struct {
Name string
Email string
}

app.Post("/submit-form", func(c *fiber.Ctx) error {
// Capture the form data
formData.Name = c.FormValue("name")
formData.Email = c.FormValue("email")

// Send a response with the captured data
return c.SendString(fmt.Sprintf("Name: %s, Email: %s", formData.Name, formData.Email))
})

app.Get("/", func(c *fiber.Ctx) error {

// Define the head with the htmx script and styling
head := elem.Head(nil,
elem.Script(elem.Attrs{attrs.Src: "https://unpkg.com/[email protected]"}),
)

// Define the body content for our form page
body := elem.Body(nil,
elem.H1(nil, elem.Text("Simple Form App")),
elem.Form(elem.Attrs{
attrs.Action: "/submit-form",
attrs.Method: "POST",
htmx.HXPost: "/submit-form",
htmx.HXSwap: "outerHTML",
},
elem.Label(elem.Attrs{attrs.For: "name"}, "Name: "),
elem.Input(elem.Attrs{
attrs.Type: "text",
attrs.Name: "name",
attrs.ID: "name",
}),
elem.Br(nil),
elem.Label(elem.Attrs{attrs.For: "email"}, "Email: "),
elem.Input(elem.Attrs{
attrs.Type: "email",
attrs.Name: "email",
attrs.ID: "email",
}),
elem.Br(nil),
elem.Input(elem.Attrs{
attrs.Type: "submit",
attrs.Value: "Submit",
}),
),
elem.Div(elem.Attrs{attrs.ID: "response"}, elem.Text("")),
)

// Wrap the head and body content within an HTML tag
pageContent := elem.Html(nil, head, body)

html := pageContent.Render()

// Specify that the response content type is HTML before sending the response
c.Type("html")
return c.SendString(html)
})

app.Listen(":3000")
}

0 comments on commit e530f38

Please sign in to comment.