1
0
View components in pure Go, that render to HTML 5. https://www.gomponents.com
Go to file
2020-12-22 11:07:33 +01:00
.github/workflows Try out codecov.io (#5) 2020-09-18 14:05:53 +02:00
assert Add package docs (#41) 2020-11-02 11:05:23 +01:00
components Add If helper function (#57) 2020-12-22 10:53:22 +01:00
examples/simple Change main example to be the dot-import version (#56) 2020-12-10 14:27:10 +01:00
html Add aria-* and role attributes (#59) 2020-12-22 11:07:33 +01:00
.editorconfig Add better example in readme (#16) 2020-09-23 22:05:59 +02:00
.gitignore Add Makefile (#4) 2020-09-18 13:57:04 +02:00
CONTRIBUTING.md Add contributing instructions (#33) 2020-10-23 14:32:55 +02:00
go.mod Add first implementation of Node, El, Attr, Text 2020-09-13 22:50:19 +02:00
gomponents_test.go Add If helper function (#57) 2020-12-22 10:53:22 +01:00
gomponents.go Add If helper function (#57) 2020-12-22 10:53:22 +01:00
LICENSE Add first implementation of Node, El, Attr, Text 2020-09-13 22:50:19 +02:00
Makefile Remove fmt.Sprintf call in attribute Render (#38) 2020-10-29 15:40:14 +01:00
README.md Simplify available elements (#55) 2020-12-10 14:20:33 +01:00

gomponents

GoDoc codecov

gomponents are declarative view components in Go, that can render to HTML5. gomponents aims to make it easy to build HTML5 pages of reusable components, without the use of a template language. Think server-side-rendered React, but without the virtual DOM and diffing.

The implementation is very usable, but the API may change until version 1 is reached.

Check out the blog post gomponents: declarative view components in Go for background.

Features

  • Build reusable view components
  • Write declarative HTML5 in Go without all the strings, so you get
    • Type safety
    • Auto-completion
    • Nice formatting with gofmt
  • Simple API that's easy to learn and use (you know most already if you know HTML)
  • No external dependencies

Usage

Get the library using go get:

go get -u github.com/maragudk/gomponents

The preferred way to use gomponents is with so-called dot-imports (note the dot before the gomponents/html import), to give you that smooth, native HTML feel:

package main

import (
	"net/http"

	g "github.com/maragudk/gomponents"
	c "github.com/maragudk/gomponents/components"
	. "github.com/maragudk/gomponents/html"
)

func main() {
	_ = http.ListenAndServe("localhost:8080", http.HandlerFunc(handler))
}

func handler(w http.ResponseWriter, r *http.Request) {
	_ = Page("Hi!", r.URL.Path).Render(w)
}

func Page(title, currentPath string) g.Node {
	return Doctype(
		HTML(
			Lang("en"),
			Head(
				TitleEl(title),
				StyleEl(Type("text/css"), g.Raw(".is-active{ font-weight: bold }")),
			),
			Body(
				Navbar(currentPath),
				H1(title),
				P(g.Textf("Welcome to the page at %v.", currentPath)),
			),
		),
	)
}

func Navbar(currentPath string) g.Node {
	return Nav(
		NavbarLink("/", "Home", currentPath),
		NavbarLink("/about", "About", currentPath),
	)
}

func NavbarLink(href, name, currentPath string) g.Node {
	return A(Href(href), c.Classes{"is-active": currentPath == href}, g.Text(name))
}

Some people don't like dot-imports, and luckily it's completely optional. If you don't like dot-imports, just use regular imports.

You could also use the provided HTML5 document template to simplify your code a bit:

package main

import (
	"net/http"

	g "github.com/maragudk/gomponents"
	c "github.com/maragudk/gomponents/components"
	. "github.com/maragudk/gomponents/html"
)

func main() {
	_ = http.ListenAndServe("localhost:8080", http.HandlerFunc(handler))
}

func handler(w http.ResponseWriter, r *http.Request) {
	_ = Page("Hi!", r.URL.Path).Render(w)
}

func Page(title, currentPath string) g.Node {
	return c.HTML5(c.HTML5Props{
		Title:    title,
		Language: "en",
		Head: []g.Node{
			StyleEl(Type("text/css"), g.Raw(".is-active{ font-weight: bold }")),
		},
		Body: []g.Node{
			Navbar(currentPath),
			H1(title),
			P(g.Textf("Welcome to the page at %v.", currentPath)),
		},
	})
}

func Navbar(currentPath string) g.Node {
	return Nav(
		NavbarLink("/", "Home", currentPath),
		NavbarLink("/about", "About", currentPath),
	)
}

func NavbarLink(href, name, currentPath string) g.Node {
	return A(Href(href), c.Classes{"is-active": currentPath == href}, g.Text(name))
}

For more complete examples, see the examples directory.

What's up with the specially named elements and attributes?

Unfortunately, there are three main name clashes in HTML elements and attributes, so they need an El or Attr suffix, respectively, to be able to co-exist in the same package in Go:

  • form (FormEl/FormAttr)
  • style (StyleEl/StyleAttr)
  • title (TitleEl/TitleAttr)