https://github.com/dv1x3r/w2go
go bindings for w2ui
https://github.com/dv1x3r/w2go
bindings crud datagrid datatable dropdown editing form go golang inline library ui w2ui
Last synced: 6 months ago
JSON representation
go bindings for w2ui
- Host: GitHub
- URL: https://github.com/dv1x3r/w2go
- Owner: dv1x3r
- License: mit
- Created: 2025-04-28T19:00:46.000Z (about 1 year ago)
- Default Branch: master
- Last Pushed: 2025-12-06T13:29:26.000Z (7 months ago)
- Last Synced: 2026-01-12T05:30:22.341Z (6 months ago)
- Topics: bindings, crud, datagrid, datatable, dropdown, editing, form, go, golang, inline, library, ui, w2ui
- Language: Go
- Homepage:
- Size: 30.3 KB
- Stars: 2
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Go bindings for w2ui
This package offers Go bindings for the [w2ui JavaScript UI Library](https://github.com/vitmalina/w2ui).
- [Features](#features)
- [Install](#install)
- [Usage](#usage)
- [w2grid](#w2grid)
- [w2form](#w2form)
- [Dropdown](#dropdown)
- [SQL Builder](#sql-builder)
- [Utils](#utils)
- [Example](#example)
- [Changelog](#changelog)
- [License](#license)
## Features
- `w2grid` support in `JSON` mode:
- **Pagination**, **sorting**, and **search**;
- **Inline editing** with typed updates;
- **Batch delete**;
- **Drag and Drop row reordering**;
- `w2form` support in `JSON` mode:
- **Record retrieval**;
- **Form submission (create/update)**;
- **Dropdowns**:
- Reusable across `w2grid` and `w2form` components;
- **Searchable** and **dynamic**;
- **SQL Builder integration**:
- Translate `w2grid` data request into SQL with `go-sqlbuilder`;
## Install
```shell
go get github.com/dv1x3r/w2go
```
## Usage
`w2go` types are JSON-serializable and work seamlessly with frameworks like `Echo` or `Fiber`, or standard `net/http`.
The following examples use Go's standard `net/http` library: `(w http.ResponseWriter, r *http.Request)`.
### w2grid
**Get Records**
```go
req, err := w2.ParseGridDataRequest(r.URL.Query().Get("request"))
if err != nil {
res := w2.NewErrorResponse(err.Error())
res.Write(w, http.StatusBadRequest)
return
}
// Process the request...
records := []Todo{{ID: 1, Name: "Buy groceries"}}
res := w2.NewGridDataResponse(records, len(records))
res.Write(w)
```
**Save Changes**
```go
req, err := w2.ParseGridSaveRequest[Todo](r.Body)
if err != nil {
res := w2.NewErrorResponse(err.Error())
res.Write(w, http.StatusBadRequest)
return
}
// Apply updates for req.Changes slice...
res := w2.NewSuccessResponse()
res.Write(w, http.StatusOK)
```
**Remove Records**
```go
req, err := w2.ParseGridRemoveRequest(r.Body)
if err != nil {
res := w2.NewErrorResponse(err.Error())
res.Write(w, http.StatusBadRequest)
return
}
// Apply updates for req.ID slice...
res := w2.NewSuccessResponse()
res.Write(w, http.StatusOK)
```
**Reorder Rows**
```go
req, err := w2.ParseGridReorderRequest(r.Body)
if err != nil {
res := w2.NewErrorResponse(err.Error())
res.Write(w, http.StatusBadRequest)
return
}
// Apply updates based on req.RecID, req.MoveBefore and req.Last...
res := w2.NewSuccessResponse()
res.Write(w, http.StatusOK)
```
### w2form
**Get Record**
```go
req, err := w2.ParseFormGetRequest(r.URL.Query().Get("request"))
if err != nil {
res := w2.NewErrorResponse(err.Error())
res.Write(w, http.StatusBadRequest)
return
}
// Process the request based on req.RecID...
record := Todo{ID: 1, Name: "Example"}
res := w2.NewFormGetResponse(record)
res.Write(w)
```
**Save Record**
```go
req, err := w2.ParseFormSaveRequest[Todo](r.Body)
if err != nil {
res := w2.NewErrorResponse(err.Error())
res.Write(w, http.StatusBadRequest)
return
}
// Insert or update based on req.RecId...
res := w2.NewFormSaveResponse(req.RecID)
res.Write(w)
```
### Dropdown
**Get Records**
```go
req, err := w2.ParseDropdownRequest(r.URL.Query().Get("request"))
if err != nil {
res := w2.NewErrorResponse(err.Error())
res.Write(w, http.StatusBadRequest)
return
}
// Process the request based on req.Max and req.Search...
records := []w2.DropdownValue{{ID: 1, Text: "Open"}, {ID: 2, Text: "Closed"}}
res := w2.NewDropdownResponse(records)
res.Write(w)
```
### SQL Builder
Use `w2sqlbuilder` with `github.com/huandu/go-sqlbuilder` to apply filters, sorters, limits, and updates.
**Apply Filters**
```go
req, _ := w2.ParseGridDataRequest(r.URL.Query().Get("request"))
// Create a SelectBuilder
sb := sqlbuilder.NewSelectBuilder()
sb.Select("t.id", "t.name")
sb.From("todo as t")
// Define the w2ui field to database field name mapping.
mapping := map[string]string{
"id": "t.id",
"name": "t.name",
}
// Apply query filters based on the request and mapping.
w2sqlbuilder.Where(sb, req, mapping)
```
**Apply Sorters**
```go
req, _ := w2.ParseGridDataRequest(r.URL.Query().Get("request"))
// Create a SelectBuilder
sb := sqlbuilder.NewSelectBuilder()
sb.Select("t.id", "t.name")
sb.From("todo as t")
// Define the w2ui field to database field name mapping.
mapping := map[string]string{
"id": "t.id",
"name": "t.name",
}
// Apply query sorters based on the request and mapping.
w2sqlbuilder.OrderBy(sb, req, mapping)
```
**Apply Limits**
```go
req, _ := w2.ParseGridDataRequest(r.URL.Query().Get("request"))
// Create a SelectBuilder
sb := sqlbuilder.NewSelectBuilder()
sb.Select("t.id", "t.name")
sb.From("todo as t")
// Apply limit and offset based on the request.
w2sqlbuilder.Limit(sb, req)
w2sqlbuilder.Offset(sb, req)
```
**Apply Updates**
Use this approach to apply **inline changes** to editable `w2grid` fields.
To track whether a field was included in the request, wrap it with the `w2.Editable` type:
```go
type Todo struct {
ID int `json:"id"`
Name string `json:"name"`
Description w2.Editable[string] `json:"description"`
Quantity w2.Editable[int] `json:"quantity"`
}
```
Update functions:
- `w2sqlbuilder.SetEditable`: updates the field only if a value **is provided**. Uses **null** if the value **is empty**.
- `w2sqlbuilder.SetEditableWithDefault`: updates the field only if a value **is provided**. Uses the **zero value** if value **is empty**.
```go
req, _ := w2.ParseGridSaveRequest[Todo](r.Body)
for _, change := range req.Changes {
ub := sqlbuilder.Update("todo")
ub.Where(ub.EQ("id", change.ID))
w2sqlbuilder.SetEditable(ub, change.Description, "description")
w2sqlbuilder.SetEditable(ub, change.Quantity, "quantity")
// ...
}
```
### Utils
- `w2sort.ReorderArray`: reorders a slice of integers based on `w2grid` drag and drop.
## Example
Run a **full** CRUD demo using in-memory SQLite:
```shell
go run example/main.go
```
Starts the server on `http://localhost:3000`
## Changelog
- v0.2.8 2025-12-06 - Update go-sqlbuilder to v1.38
- v0.2.7 2025-10-19 - EditableDropdown support for clean w2form records
- v0.2.6 2025-05-24 - Write methods now return errors
- v0.2.5 2025-05-16 - First stable release
## License
Licensed under the MIT license.