domui: DOM UI framework for Go

domui: DOM UI framework for Go

Features

  • Pure go code compiled to wasm
    • Utilizing Go's excellent support for static typing and dynamic reflection
    • Runs on any WebAssembly and DOM supported browsers, Electron, etc
  • Dependent reactive system for both view and state management
    • Conceptually unify view component and state management
    • No hooks, redux, recoil, mobx ...
  • Auto and efficient DOM tree updating
    • Based on virtual DOM diff and patch

Prerequisites

  • Go compiler 1.16 or newer
  • If you are not familiar with compiling and running WebAssembly program, please read the official wiki

Table of contents

Tutorial

Minimal runnable program

Hello, world!
return Div(T("Hello, world!")) } func main() { domui.NewApp( // render on
js.Global().Get("document").Call("getElementById", "app"), // pass Def's methods as definitions domui.Methods(new(Def))..., ) // prevent from exiting time.Sleep(time.Hour * 24 * 365 * 100) } ">
package main

import (
	"github.com/reusee/domui"
	"syscall/js"
	"time"
)

// ergonomic aliases
var (
	Div = domui.Tag("div")
	T   = domui.Text
)

// A type to hold all definitions
type Def struct{}

// define the root UI element
func (_ Def) RootElement() domui.RootElement {
	// same to 
Hello, world!
return Div(T("Hello, world!")) } func main() { domui.NewApp( // render on
js.Global().Get("document").Call("getElementById", "app"), // pass Def's methods as definitions domui.Methods(new(Def))..., ) // prevent from exiting time.Sleep(time.Hour * 24 * 365 * 100) }

The dependent system

The definition of RootElement can be refactored to multiple dependent components.

package main

import (
	"github.com/reusee/domui"
	"syscall/js"
	"time"
)

var (
	Div = domui.Tag("div")
	T   = domui.Text
)

type (
	Def  struct{}
	Spec = domui.Spec
)

// A string-typed state
type Greetings string

// define Greetings
func (_ Def) Greetings() Greetings {
	return "Hello, world!"
}

// An UI element
type GreetingsElement Spec

// define GreetingsElement
func (_ Def) GreetingsElement(
	// use Greetings
	greetings Greetings,
) GreetingsElement {
	return Div(T("%s", greetings))
}

// The root UI element
func (_ Def) RootElement(
	// use GreetingsElement
	greetingsElem GreetingsElement,
) domui.RootElement {
	return Div(
		greetingsElem,
	)
}

func main() {
	domui.NewApp(
		js.Global().Get("document").Call("getElementById", "app"),
		domui.Methods(new(Def))...,
	)
	time.Sleep(time.Hour * 24 * 365 * 100)
}

The reactive system

Definitions can be updated. All affected definitions will be re-calculated recursively till the RootElement.

package main

import (
	"github.com/reusee/domui"
	"syscall/js"
	"time"
)

var (
	Div     = domui.Tag("div")
	T       = domui.Text
	OnClick = domui.On("click")
)

type (
	Def    struct{}
	Spec   = domui.Spec
	Update = domui.Update
)

type Greetings string

func (_ Def) Greetings() Greetings {
	return "Hello, world!"
}

type GreetingsElement Spec

func (_ Def) GreetingsElement(
	greetings Greetings,
) GreetingsElement {
	return Div(T("%s", greetings))
}

func (_ Def) RootElement(
	greetingsElem GreetingsElement,
	// use the Update function
	update Update,
) domui.RootElement {
	return Div(
		greetingsElem,

		// when clicked, do update
		OnClick(func() {
			// provide a new definition for Greetings
			update(func() Greetings {
				return "Hello, DomUI!"
			})
		}),
	)
}

func main() {
	domui.NewApp(
		js.Global().Get("document").Call("getElementById", "app"),
		domui.Methods(new(Def))...,
	)
	time.Sleep(time.Hour * 24 * 365 * 100)
}

DOM element specifications

The above programs demonstrated tag and event usages. Attributes, styles, classes can also be specified.

package main

import (
	"github.com/reusee/domui"
	"syscall/js"
	"time"
)

var (
	Div        = domui.Tag("div")
	Link       = domui.Tag("a")
	Ahref      = domui.Attr("href")
	Sfont_size = domui.Style("font-size")
	T          = domui.Text
	ID         = domui.ID
	Class      = domui.Class
)

type Def struct{}

func (_ Def) RootElement() domui.RootElement {
	return Div(
		Link(
			T("Hello, world!"),
			// id
			ID("link"),
			// class
			Class("link1", "link2"),
			// href attribute
			Ahref("http://github.com"),
			// font-size style
			Sfont_size("1.6rem"),
		),
	)
}

func main() {
	domui.NewApp(
		js.Global().Get("document").Call("getElementById", "app"),
		domui.Methods(new(Def))...,
	)
	time.Sleep(time.Hour * 24 * 365 * 100)
}

Parameterized element

To make a reusable element, define it as a function.

package main

import (
	"fmt"
	"github.com/reusee/domui"
	"reflect"
	"strings"
	"syscall/js"
	"time"
)

var (
	Div     = domui.Tag("div")
	T       = domui.Text
	OnClick = domui.On("click")
)

type (
	Def    struct{}
	any    = interface{}
	Spec   = domui.Spec
	Update = domui.Update
	Specs  = domui.Specs
)

// Greetings with name parameter
type Greetings func(name any) Spec

func (_ Def) Greetings(
	update Update,
) Greetings {
	return func(name any) Spec {
		return Specs{
			T("Hello, %s!", name),
			OnClick(func() {
				// when clicked, update the name argument to upper case
				// use reflect to support all string-typed arguments
				nameValue := reflect.New(reflect.TypeOf(name))
				nameValue.Elem().SetString(
					strings.ToUpper(fmt.Sprintf("%s", name)))
				update(nameValue.Interface())
			}),
		}
	}
}

// string-typed states
type (
	TheWorld string
	TheDomUI string
)

// define two types in one function
func (_ Def) Names() (TheWorld, TheDomUI) {
	return "world", "DomUI"
}

func (_ Def) RootElement(
	greetings Greetings,
	world TheWorld,
	domUI TheDomUI,
) domui.RootElement {
	return Div(
		// use Greetings
		Div(
			greetings(world),
		),
		Div(
			greetings(domUI),
		),
	)
}

func main() {
	domui.NewApp(
		js.Global().Get("document").Call("getElementById", "app"),
		domui.Methods(new(Def))...,
	)
	time.Sleep(time.Hour * 24 * 365 * 100)
}

Miscellaneous usages

When updating a definition that has no dependency, instead of passing a function, a pointer can be used.

newGreetings := Greetings("Hello!")
update(&newGreetings)
// is the same to
update(func() Greetings {
  return "Hello!"
})

To do something on App inits, define one or more OnAppInit

func (_ Def) InitFoo() domui.OnAppInit {
  // do something
}

func (_ Def) InitBar() domui.OnAppInit {
  // do something
}

To access the DOM element in an event handler, use a js.Value parameter

type Foo Spec

func (_ Def) Foo() Foo {
  retrun Div(
    OnClick(func(elem js.Value) {
      _ = elem.Call("getAttribute", "href").String()
    }),
  )
}

Specs can be cached for reusing

type Article func(title string, content string) Spec

func (_ Def) Article() Article {
  m := domui.NewSpecMap()
  return m(
    // key
    [2]any{title, content},
    // value
    func() Spec {
      return Div( /* ... */ )
    },
  )
}

Some conditional Spec constructors are provided

var (
  A = domui.Tag("a")
  Ahref = domui.Attr("href")
  Sfont_weight = domui.Style("font-weight")
)

type Link func(href string, bold bool) Spec

func (_ Def) Link() Link {
  return func(href string, bold bool) Spec {
    return A(
      // If
      domui.If(href != "", Ahref(href)),
      // Alt
      domui.Alt(bold,
        Sfont_weight("bold"),
        Sfont_weight("normal"),
      ),
    )
  }
}

And loop constructors

type List func(elems []string) Spec

func (_ Def) List() List {
  return func(elems []string) Spec {
    return Div(
      // For
      domui.For(elems, func(s string) Spec {
        return Div(T("%s", s))
      }),
      // Range
      domui.Range(elems, func(i int, s string) Spec {
        return Div(T("%d: %s", i, s))
      }),
    )
  }
}
Similar Resources

7 days golang programs from scratch (web framework Gee, distributed cache GeeCache, object relational mapping ORM framework GeeORM, rpc framework GeeRPC etc) 7天用Go动手写/从零实现系列

7 days golang programs from scratch README 中文版本 7天用Go从零实现系列 7天能写什么呢?类似 gin 的 web 框架?类似 groupcache 的分布式缓存?或者一个简单的 Python 解释器?希望这个仓库能给你答案

Jan 5, 2023

Flamingo Framework and Core Library. Flamingo is a go based framework for pluggable web projects. It is used to build scalable and maintainable (web)applications.

Flamingo Framework and Core Library. Flamingo is a go based framework for pluggable web projects. It is used to build scalable and maintainable (web)applications.

Flamingo Framework Flamingo is a web framework based on Go. It is designed to build pluggable and maintainable web projects. It is production ready, f

Jan 5, 2023

Golanger Web Framework is a lightweight framework for writing web applications in Go.

/* Copyright 2013 Golanger.com. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except

Nov 14, 2022

Flamingo Framework and Core Library. Flamingo is a go based framework for pluggable web projects. It is used to build scalable and maintainable (web)applications.

Flamingo Framework and Core Library. Flamingo is a go based framework for pluggable web projects. It is used to build scalable and maintainable (web)applications.

Flamingo Framework Flamingo is a web framework based on Go. It is designed to build pluggable and maintainable web projects. It is production ready, f

Jan 5, 2023

Golanger Web Framework is a lightweight framework for writing web applications in Go.

/* Copyright 2013 Golanger.com. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except

Nov 14, 2022

GoCondor is a golang web framework with an MVC like architecture, it's based on Gin framework

GoCondor is a golang web framework with an MVC like architecture, it's based on Gin framework

GoCondor is a golang web framework with an MVC like architecture, it's based on Gin framework, it features a simple organized directory structure for your next project with a pleasant development experience, made for developing modern APIs and microservices.

Dec 29, 2022

The jin is a simplified version of the gin web framework that can help you quickly understand the core principles of a web framework.

jin About The jin is a simplified version of the gin web framework that can help you quickly understand the core principles of a web framework. If thi

Jul 14, 2022

laravel for golang,goal,fullstack framework,api framework

laravel for golang,goal,fullstack framework,api framework

laravel for golang,goal,fullstack framework,api framework

Feb 24, 2022

Rpcx-framework - An RPC microservices framework based on rpcx, simple and easy to use, ultra fast and efficient, powerful, service discovery, service governance, service layering, version control, routing label registration.

RPCX Framework An RPC microservices framework based on rpcx. Features: simple and easy to use, ultra fast and efficient, powerful, service discovery,

Jan 5, 2022

terraform-plugin-mux Example (framework + framework)

Terraform Provider Scaffolding (Terraform Plugin Framework) This template repository is built on the Terraform Plugin Framework. The template reposito

Feb 8, 2022

Gin is a HTTP web framework written in Go (Golang).

Gin is a HTTP web framework written in Go (Golang).

Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.

Jan 3, 2023

Simple yet customizable bot framework written in Go.

Simple yet customizable bot framework written in Go.

Introduction Sarah is a general-purpose bot framework named after the author's firstborn daughter. This comes with a unique feature called "stateful c

Dec 12, 2022

Golang Framework for writing Slack bots

hanu - Go for Slack Bots! The Go framework hanu is your best friend to create Slack bots! hanu uses allot for easy command and request parsing (e.g. w

Oct 24, 2022

Telegram Bot Framework for Go

Margelet Telegram Bot Framework for Go is based on telegram-bot-api It uses Redis to store it's states, configs and so on. Any low-level interactions

Dec 22, 2022

Slack Bot Framework

slacker Built on top of the Slack API github.com/slack-go/slack with the idea to simplify the Real-Time Messaging feature to easily create Slack Bots,

Dec 25, 2022

Slack bot core/framework written in Go with support for reactions to message updates/deletes

Slack bot core/framework written in Go with support for reactions to message updates/deletes

Overview Requirements Features Demo The Name Concepts Create Your Own Slackscot Assembling the Parts and Bringing Your slackscot to Life Configuration

Oct 28, 2022

Telebot is a Telegram bot framework in Go.

Telebot "I never knew creating Telegram bots could be so sexy!" go get -u gopkg.in/tucnak/telebot.v2 Overview Getting Started Poller Commands Files Se

Dec 30, 2022

Another CLI framework for Go. It works on my machine.

Another CLI framework for Go. It works on my machine.

Command line interface framework Go framework for rapid command line application development

Dec 30, 2022

An opinionated configuration loading framework for Containerized and Cloud-Native applications.

An opinionated configuration loading framework for Containerized and Cloud-Native applications.

Opinionated configuration loading framework for Containerized and 12-Factor compliant applications. Read configurations from Environment Variables, an

Dec 16, 2022
Comments
  • Static Site Generator

    Static Site Generator

    Hi, is it possible to use this to create a static site? using domui as a development tool, is very interesting. The ability to generate a static site on the fly could be very interesting on sites that don’t change so often.

gosx-notifier is a Go framework for sending desktop notifications to OSX 10.8 or higher
gosx-notifier is a Go framework for sending desktop notifications to OSX 10.8 or higher

gosx-notifier A Go lib for sending desktop notifications to OSX Mountain Lion's (10.8 or higher REQUIRED) Notification Center. Update 4/3/2014 On OSX

Dec 28, 2022
Windows GUI framework for Go.

gform is an easy to use Windows GUI toolkit for Go It provides two approaches to create UI. 1. Pure code. gform.Init() mainWindow := gform.NewForm(ni

Jan 1, 2023
Cross platform rapid GUI framework for golang based on Dear ImGui.
Cross platform rapid GUI framework for golang based on Dear ImGui.

giu Cross platform rapid GUI framework for golang based on Dear ImGui and the great golang binding imgui-go. Any contribution (features, widgets, tuto

Dec 28, 2022
Pglet - Web UI framework for backend developers
Pglet - Web UI framework for backend developers

Pglet - Web UI framework for backend developers

Nov 15, 2022
Cross-Platform GUI Framework for Go

⚠️ I'm currently working on this project as part of my master's thesis at the Berlin University of Applied Sciences and Technology. It is under active

Oct 31, 2022
DOM library for Go and WASM

Go DOM binding (and more) for WebAssembly This library provides a Go API for different Web APIs for WebAssembly target. It's in an active development,

Dec 23, 2022
Go Lang Web Assembly bindings for DOM, HTML etc

WebAPI Go Language Web Assembly bindings for DOM, HTML etc WARNING: The current API is in very early state and should be consider to be expremental. T

Dec 28, 2022
hdq - HTML DOM Query Language for Go+

hdq - HTML DOM Query Language for Go+ Summary about hdq hdq is a Go+ package for processing HTML documents. Tutorials Collect links of a html page How

Dec 13, 2022
Gom: DOM building using Go

gom DOM building using Go Usage package main import "github.com/hadihammurabi/gom" func main() { dom := gom.H("html").Children( gom.H("head").Chi

Dec 16, 2021
Dom - A Go API for different Web APIs for WebAssembly target

Go DOM binding (and more) for WebAssembly This library provides a Go API for dif

Jan 7, 2023