Build cross platform GUI apps with GO and HTML/JS/CSS (powered by nwjs)

gowd

Build cross platform GUI apps with GO and HTML/JS/CSS (powered by nwjs)

CircleCI Go Report Card GoDoc

How to use this library:

  1. Download and install nwjs
  2. Install this library go get github.com/dtylman/gowd
  3. Clone this repo.
  4. Place package.json, index.html, main.go and main.js from template in a new folder.
  5. go build
  6. Edit main.js and set goBinary to your your executable name:
    var goBinary = "./template"; //or template.exe
  7. Run nw ., the hello world template should appear: hello-world

Usage

Simplest "hello world":

import "github.com/dtylman/gowd"

func main() {
	body, err := gowd.ParseElement("<h1>Hello world</h1>", nil)
	if err != nil {
		panic(err)
	}
	gowd.Run(body)
}

Adding a button:

import (
	"github.com/dtylman/gowd"
)

func main() {
	body, err := gowd.ParseElement("<h1>Hello world</h1>", nil)
	if err != nil {
		panic(err)
	}
	p := body.AddElement(gowd.NewElement("p"))
	btn := p.AddElement(gowd.NewElement("button"))
	btn.SetText("Click me")
	btn.OnEvent(gowd.OnClick, btnClicked)
	gowd.Run(body)
}

func btnClicked(sender *gowd.Element, event *gowd.EventElement) {
	sender.SetText("Clicked!")
}

Creating and binding from HTML:

import (
	"github.com/dtylman/gowd"
	"fmt"
)

func main() {
	body, err := gowd.ParseElement("<h1>Hello world</h1>", nil)
	if err != nil {
		panic(err)
	}
	p := body.AddElement(gowd.NewElement("p"))
	em := gowd.NewElementMap()
	p.AddHtml(`<select id="select1">
		<option value="" disabled="disabled" selected="selected">Please select a name</option>
		<option value="1">One</option>
		<option value="2">Two</option>
		</select>`, em)
	em["select1"].OnEvent(gowd.OnChange, btnClicked)
	em["select1"].Object = body
	gowd.Run(body)
}

func btnClicked(sender *gowd.Element, event *gowd.EventElement) {
	body := sender.Object.(*gowd.Element)
	body.AddElement(gowd.NewStyledText(fmt.Sprintf("Selected %s", event.GetValue()), gowd.BoldText))
	body.AddElement(gowd.NewElement("br"))
}

Using bootstrap:

'gowd' supports creating bootstrap elements using the bootstrap package.

First, add bootsrap css and js to your index.html file:

    <script type="text/javascript" src="js/jquery.min.js"></script>
    <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/>
    <script type="text/javascript" src="js/bootstrap.min.js"></script>

Then you can create bootsrap items:

import (
	"github.com/dtylman/gowd"

	"github.com/dtylman/gowd/bootstrap"
	"time"
	"fmt"
)

var body *gowd.Element

func main() {
	//creates a new bootstrap fluid container
	body = bootstrap.NewContainer(false)
	// add some elements using the object model
	div := bootstrap.NewElement("div", "well")
	row := bootstrap.NewRow(bootstrap.NewColumn(bootstrap.ColumnLarge, 6, div))
	body.AddElement(row)
	// add some other elements from HTML
	div.AddHTML(`<div class="dropdown">
	<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Dropdown Example
	<span class="caret"></span></button>
	<ul class="dropdown-menu" id="dropdown-menu">
	<li><a href="#">HTML</a></li>
	<li><a href="#">CSS</a></li>
	<li><a href="#">JavaScript</a></li>
	</ul>
	</div>`, nil)
	// add a button to show a progress bar
	btn := bootstrap.NewButton(bootstrap.ButtonPrimary, "Start")
	btn.OnEvent(gowd.OnClick, btnClicked)
	row.AddElement(bootstrap.NewColumn(bootstrap.ColumnLarge, 4, bootstrap.NewElement("div", "well", btn)))

	//start the ui loop
	gowd.Run(body)
}

// happens when the 'start' button is clicked
func btnClicked(sender *gowd.Element, event *gowd.EventElement) {
	// adds a text and progress bar to the body 
	text := body.AddElement(gowd.NewStyledText("Working...", gowd.BoldText))
	progressBar := bootstrap.NewProgressBar()
	body.AddElement(progressBar.Element)
	
	// makes the body stop responding to user events
	body.Disable()
	
	// clean up - remove the added elements
	defer func() {
		body.RemoveElement(text)
		body.RemoveElement(progressBar.Element)
		body.Enable()
	}()

	// render the progress bar
	for i := 0; i <= 123; i++ {
		progressBar.SetValue(i, 123)
		text.SetText(fmt.Sprintf("Working %v", i))
		time.Sleep(time.Millisecond * 20)
		// this will cause the body to be refreshed
		body.Render()
	}

}

This will yield the following app:

Simple

More a more advanced usage, see the Todo sample

TodoMVC

Comments
  • <select> element on event changes to first option.

    , b.em) pnl.AddToBody(div) b.em["lstEmpresas"].OnEvent(gowd.OnChange, b.onChangeLstEmpresa)

    i have 3 value in a select element, when the onchange event is called works and i can get de option... But when the event finishes, the option is changed to the first option.

    How i can solve this issue?

  • create ExecJS to nicely execute JS code without messing with DOM

    create ExecJS to nicely execute JS code without messing with DOM

    this allows for other plugins for other CSS libraries to nicely execute code whenever needed. MDL for example, needs to execute JS code for certain components to work.

    the snackbar needs to run JS code to open, but if it runs before the HTMLDOM is updated it will not run properly and not show the snackbar.

  • Bundle nwjs during build for a standalone executable?

    Bundle nwjs during build for a standalone executable?

    Hi, pardon my inexperience. Looks like this project requires nwjs installed to run?

    I like go in that it can build self contained binaries that tend to also be small footprint. It would be nice for future enhancement to build scaffolding on top of this project such that you can bundle the nwjs requirement into the compiled go binary so that instead of

    nw . in the current path where the code is compiled, we could do ./myGoAppName, and where we can use go build and go install (or some other final build process) on the scaffolding to produce a standalone self-contained binary that will run w/o installing nwjs for it is packaged in with the compiled app.

    Initially this could just target the platform being built on, and later look into cross-compile support (compile once and you get binaries for *nix, Mac, Windows).

    For me, w/o the self contained binary feature, I don't see that much benefit of go w/ nwjs, I could just use other language with it instead.

  • When I try to run the todomvc code, I get

    When I try to run the todomvc code, I get "Process exited with code -4058".

    I am also having a separate error but I understand that it is not harmful:

    MINGW64 ~/go/src/github.com/dtylman/gowd/cmd/todomvc (master) $ ~/nw/nw . [10864:5888:0303/195421.396:ERROR:device_event_log_impl.cc(211)] [19:54:21.396] USB: usb_device_handle_win.cc:1049 Failed to read descriptor from node connection: A device attached to the system is not functioning. (0x1F) [10864:5888:0303/195421.400:ERROR:device_event_log_impl.cc(211)] [19:54:21.400] USB: usb_device_handle_win.cc:1049 Failed to read descriptor from node connection: A device attached to the system is not functioning. (0x1F)

  • Example of FileButton

    Example of FileButton

    Hi, Can you give an example of how to use FileButton to receive a selected filename in gowd?

    I have tried:

    package main
    
    import (
    	"github.com/dtylman/gowd"
    	"github.com/dtylman/gowd/bootstrap"
    	"fmt"
    )
    
    var body *gowd.Element
    
    func main() {
    	//creates a new bootstrap fluid container
    	body = bootstrap.NewContainer(false)
    	// add some elements using the object model
    	div := bootstrap.NewElement("div", "well")
    	row := bootstrap.NewRow(bootstrap.NewColumn(bootstrap.ColumnSmall, 3, div))
    	// add a button to show a progress bar
    	btn := bootstrap.NewFileButton(bootstrap.ButtonPrimary, "Upload File", false)
    	btn.OnEvent(gowd.OnChange, btnFileUploaded)
    	div.AddElement(btn.Element)
    	body.AddElement(row)
    	
    	//start the ui loop
    	gowd.Run(body)
    }
    
    // happens when the file is added to the FileButton above
    func btnFileUploaded(sender *gowd.Element, event *gowd.EventElement) {
    	body.AddElement(gowd.NewStyledText(fmt.Sprintf("Selected %s", sender.GetValue()), gowd.BoldText))
    	body.AddElement(gowd.NewElement("br"))
    }
    

    and no filename is shown when I select a file. I also tried:

    // happens when the file is added to the FileButton above
    func btnFileUploaded(sender *gowd.Element, event *gowd.EventElement) {
            fileButton := sender.Object.(*bootstrap.FileButton)
    	body.AddElement(gowd.NewStyledText(fmt.Sprintf("Selected %s", fileButton.GetValue()), gowd.BoldText))
    	body.AddElement(gowd.NewElement("br"))
    }
    

    and this also failed.

  • Cannot set text of a text area.

    Cannot set text of a text area.

    Hello,

    First off, I would like to say that I am glad I found this library because I really like it.

    Now, my issue is that whenever I try and set the text of a textarea element using element.SetText(), it will clear all my elements(the body). I am not sure why this happens but thought that maybe you could look into it.

    Thanks!

  • Very confused by installation intructions

    Very confused by installation intructions

    Hey!

    I want to use NW.js in my Go project, but I have absolutely no experience from installing it. I am very confused by the steps in your installation instruction. Would be great if you could write an ELI5 version of it.

    Cheers!

  • Request to move repo under NW Userland

    Request to move repo under NW Userland

    Hi @dtylman,

    I'm part of a GitHub org called NW Utils. I'm trying to consolidate NW tooling so it's easier to find useful projects and give much needed life to stagnant ones. I also think this would be a great opportunity to exchange ideas and learn new things. Let me know what you think and if you’d be willing to.

    Best Regards Ayushman

  • Strip CRLFs when parsing HTML

    Strip CRLFs when parsing HTML

    passing line breaks in side innerHTML param to ParseElement causes line breaks to appear in the generated output, causing malformed UI to be passed to nwjs.

  • Clarify installation required in README

    Clarify installation required in README

    Currently the readme implies that the library should be used as-is after cloning, rather than being installed via the go tool. Pull request edits the readme to make the process clearer.

  • Kita is a declarative, reactive GUI toolkit for build cross platform apps with web technology with single codebase
    Kita is a declarative, reactive GUI toolkit for build cross platform apps with web technology with single codebase

    Kita is a declarative, reactive GUI toolkit for build cross platform apps with web technology with single codebase. Inspired by Flutter, React. S

    Apr 18, 2022
    UIKit - A declarative, reactive GUI toolkit for build cross platform apps with web technology with single codebase
     UIKit - A declarative, reactive GUI toolkit for build cross platform apps with web technology with single codebase

    UIKit - A declarative, reactive GUI toolkit for build cross platform apps with web technology with single codebase

    Apr 18, 2022
    Build cross-platform modern desktop apps in Go + HTML5
    Build cross-platform modern desktop apps in Go + HTML5

    Lorca A very small library to build modern HTML5 desktop apps in Go. It uses Chrome browser as a UI layer. Unlike Electron it doesn't bundle Chrome in

    Jan 6, 2023
    Cross-platform GUI for go is never this easy and clean.
    Cross-platform GUI for go is never this easy and clean.

    gimu Strongly suggest NOT to use this project anymore, the auto-generated cgo wrapper of Nuklear has a random crash issue which is hard to fix (becaus

    Jul 12, 2022
    Golang bindings of Sciter: the Embeddable HTML/CSS/script engine for modern UI development
    Golang bindings of Sciter: the Embeddable HTML/CSS/script engine for modern UI development

    Go bindings for Sciter Check this page for other language bindings (Delphi / D / Go / .NET / Python / Rust). Attention The ownership of project is tra

    Dec 23, 2022
    Cross platform GUI in Go based on Material Design
    Cross platform GUI in Go based on Material Design

    About Fyne is an easy to use UI toolkit and app API written in Go. It is designed to build applications that run on desktop and mobile devices with a

    Jan 3, 2023
    RobotGo, Go Native cross-platform GUI automation @vcaesar

    Robotgo Golang Desktop Automation. Control the mouse, keyboard, bitmap, read the screen, Window Handle and global event listener. RobotGo supports Mac

    Jan 7, 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
    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
    Cross-platform Go/Golang GUI library.

    中文 | English GoVCL Cross-platform Golang GUI library, The core binding is liblcl, a common cross-platform GUI library created by Lazarus. GoVCL is a n

    Dec 30, 2022
    Common library for Go GUI apps on Windows
    Common library for Go GUI apps on Windows

    winc Common library for Go GUI apps on Windows. It is for Windows OS only. This makes library smaller than some other UI libraries for Go.

    Dec 12, 2022
    Platform-native GUI library for Go.

    ui: platform-native GUI library for Go This is a library that aims to provide simple GUI software development in Go. It is based on my libui, a simple

    Jan 9, 2023
    A package to build progressive web apps with Go programming language and WebAssembly.
    A package to build progressive web apps with Go programming language and WebAssembly.

    go-app is a package to build progressive web apps (PWA) with Go programming language and WebAssembly. It uses a declarative syntax that allows creatin

    Dec 28, 2022
    Tiny cross-platform webview library for C/C++/Golang. Uses WebKit (Gtk/Cocoa) and Edge (Windows)

    webview A tiny cross-platform webview library for C/C++/Golang to build modern cross-platform GUIs. Also, there are Rust bindings, Python bindings, Ni

    Dec 28, 2022
    Go cross-platform library for displaying dialogs and input boxes

    dlgs dlgs is a cross-platform library for displaying dialogs and input boxes. Installation go get -u github.com/gen2brain/dlgs Documentation Document

    Dec 24, 2022
    Tiny cross-platform webview library for C/C++/Golang. Uses WebKit (Gtk/Cocoa) and Edge (Windows)

    webview A tiny cross-platform webview library for C/C++/Golang to build modern cross-platform GUIs. Also, there are Rust bindings, Python bindings, Ni

    Jan 1, 2023
    An experimental Go cross platform UI library.

    GXUI - A Go cross platform UI library. Notice: Unfortunately due to a shortage of hours in a day, GXUI is no longer maintained. If you're looking for

    Jan 6, 2023
    Cross-platform Go library to place an icon in the host operating system's taskbar.

    trayhost Package trayhost is a cross-platform Go library to place an icon in the host operating system's taskbar. Platform Support macOS - Fully imple

    Nov 6, 2022
    A cross-platform app-development module for Go.
    A cross-platform app-development module for Go.

    The cross-platform Go module for building apps (pronounced klo-va-seed). Usecases As a lightweight alternative to Electron Write your frontend and nat

    Dec 1, 2022