Home

Awesome

🔨 HTMX

Test & Build Go Reference Go Report Card License: MIT Taylor Swift

A Go package to write HTML5 and HTMX components in Go. The package is designed to work with fiber and htmx.

Features

Installation

go get github.com/zeiss/fiber-htmx
ht

The available web components are published in the fiber-htmx package.

htmx.HTML5(
    htmx.HTML5Props{
        Head: []htmx.Node{
            htmx.Script(
                htmx.Src("https://unpkg.com/fiber-htmx@1.3.32"),
            ),
            htmx.Link(
                htmx.Rel("stylesheet"),
                htmx.Href("https://unpkg.com/fiber-htmx@1.3.32/dist/out.css"),
            ),
        },
    },
    htmx.Body(
        htmx.ClassNames{},
        htmx.Toasts(),
    ),
)

Example

Creating a button leveraging htmx is as easy as this.

htmx.Button(
    htmx.Attribute("type", "submit")
    htmx.Text("Button"),
    htmx.HxPost("/api/respond")
)

There are additional complex components that help to write HTML5 and HTMX components in Go.

Elements

HTML and HTMX elements are represented as functions in Go. The functions are used to create the elements.

htmx.Div(
    htmx.ClassNames{
        tailwind.FontSemibold: true,
    },
    htmx.Text("Hello World"),
)

This will create the following HTML element.

<div class="font-semibold">Hello World</div>

There is support for all HTML5 elements and Tailwind classes. Use import "github.com/zeiss/fiber-htmx/tailwind" to include Tailwind classes.

Components

Write HTML5 and HTMX components in Go.

func HelloWorld() htmx.Node {
    return htmx.Div(
        htmx.ClassNames{
            "font-semibold",
        },
        htmx.Text("Hello World"),
    )
}

There are different types of composition. For example, passing children to a component.

func HelloWorld(children ...htmx.Node) htmx.Node {
    return htmx.Div(
        htmx.ClassNames{
            "font-semibold",
        },
        htmx.Text("Hello World"),
        htmx.Div(
            htmx.ClassNames{
                "text-red-500",
            },
            htmx.Group(children...),
        ),
    )
}

Styling of components is done with the htmx.ClassNames type.

func HelloWorld() htmx.Node {
    return htmx.Div(
        htmx.ClassNames{
            tailwind.FontSemibold: true,
            "text-red-500": true,
        },
        htmx.Text("Hello World"),
    )
}

There are also helpers to make the life with styling easier by merging classes.

func HelloWorld(classes htmx.ClassNames) htmx.Node {
    return htmx.Div(
        htmx.Merge(
            htmx.ClassNames{
                "font-semibold",
                "text-red-500",
            },
            classes,
        )
        htmx.Text("Hello World"),
    )
}

There is also the option to use htmx.Controller to encapsulate the logic of the components.


func NewHelloWorldController() htmx.ControllerFactory {
  return func() htmx.Controller {
    return &NewHelloWorldController{}
  }
}

type HelloWorldController struct {
    htmx.DefaultController
}

func (c *HelloWorldController) Get() error {
    return c.Render(
      htmx.HTML5(
            htmx.HTML5Props{
                Title:    "index",
                Language: "en",
                Head: []htmx.Node{},
            },
            htmx.Div(
                htmx.ClassNames{},
                htmx.Text("Hello World"),
            ),
        ),
    )    
}

app := fiber.New()
app.Get("/", htmx.NewHxControllerHandler(NewHelloWorldController()))

app.Listen(":3000")

Server-side events (SSE)

The package supports server-side events (SSE) to update the components on the client-side.

manager := sse.NewBroadcastManager(5)
app.Get("/sse", sse.NewSSEHandler(manager))

Error Handling

There are components that enable handling fallbacks in case of errors and to recover from panics in rendering components.

htmx.Fallback(
  htmx.ErrorBoundary(
    func() htmx.Node {
      return utils.Panic(errors.New("panic"))
    },
  ),
  htmx.Text("Fallback"),
),

Examples

See examples to understand the provided interfaces.

Benchmarks

BenchmarkElement-10                     12964440                77.40 ns/op
Benchmark_AttrRender-10                 16038232                74.15 ns/op
Benchmark_HTML5_Render-10                   1392            847193 ns/op
Benchmark_ClassNames_Render-10           3166761               378.2 ns/op

Rendering 10.000 nodes took >0.8ms. The package is fast enough to render HTML5 and HTMX components.

License

MIT