Inline Click To Edit

List view of items with a click to edit button and persistence

NameDate of BirthRoleSalary

John Doe

24/05/1995

htmgo developer

$250,000

Jake Smith

24/05/1995

htmx developer

$100,000

Source Code

Copy
  1package snippets
  2
  3import (
  4	"fmt"
  5	"github.com/maddalax/htmgo/framework/h"
  6)
  7
  8// RowClasses defined here for simplicity of the example
  9var RowClasses = "whitespace-nowrap px-4 py-4 font-medium text-gray-900 text-left"
 10var ButtonClasses = "inline-block rounded bg-slate-900 px-4 py-2 text-xs font-medium text-white hover:bg-slate-800"
 11var InputClasses = "-ml-2 max-w-[125px] border p-2 rounded focus:outline-none focus:ring focus:ring-slate-800"
 12
 13type Record struct {
 14	Id       string
 15	Name     string
 16	Birthday string
 17	Role     string
 18	Salary   string
 19}
 20
 21var records = []Record{
 22	{
 23		Id:       "1",
 24		Name:     "John Doe",
 25		Birthday: "24/05/1995",
 26		Role:     "htmgo developer",
 27		Salary:   "$250,000",
 28	},
 29	{
 30		Id:       "2",
 31		Name:     "Jake Smith",
 32		Birthday: "24/05/1995",
 33		Role:     "htmx developer",
 34		Salary:   "$100,000",
 35	},
 36}
 37
 38func ClickToEdit(ctx *h.RequestContext) *h.Partial {
 39	return h.NewPartial(
 40		h.Div(
 41			h.Class("flex gap-2 items-center w-full"),
 42			Table(),
 43		),
 44	)
 45}
 46
 47// StartEditing is a partial that is called when the user clicks on the edit button,
 48// it will swap in the form for editing for the given record
 49func StartEditing(ctx *h.RequestContext) *h.Partial {
 50	id := ctx.QueryParam("id")
 51
 52	record := h.Find(records, func(record *Record) bool {
 53		return record.Id == id
 54	})
 55
 56	if record == nil {
 57		return h.EmptyPartial()
 58	}
 59
 60	return h.SwapManyPartial(
 61		ctx,
 62		TableRow(record, true),
 63	)
 64}
 65
 66// SaveEditing is a partial that is called when the user clicks on the save button while editing,
 67// it will update the record with the new values and swap it back out
 68// note: in the example, we are just creating a new record in memory instead of updating the existing one,
 69// normally you would update a persistent record in a database
 70func SaveEditing(ctx *h.RequestContext) *h.Partial {
 71	id := ctx.QueryParam("id")
 72
 73	// just for the example, create  a new record so it doesn't affect the global original
 74	record := Record{
 75		Id:       id,
 76		Name:     ctx.FormValue("name"),
 77		Birthday: ctx.FormValue("birthday"),
 78		Role:     ctx.FormValue("role"),
 79		Salary:   ctx.FormValue("salary"),
 80	}
 81
 82	return h.SwapPartial(ctx, TableRow(&record, false))
 83}
 84
 85func Table() *h.Element {
 86	return h.Div(
 87		h.Class("overflow-x-auto w-full"),
 88		h.Table(
 89			h.Class("divide-y divide-gray-200 bg-white table-fixed"),
 90			h.THead(
 91				h.Tr(
 92					h.Th(
 93						h.Class(RowClasses),
 94						h.Text("Name"),
 95					),
 96					h.Th(
 97						h.Class(RowClasses),
 98						h.Text("Date of Birth"),
 99					),
100					h.Th(
101						h.Class(RowClasses),
102						h.Text("Role"),
103					),
104					h.Th(
105						h.Class(RowClasses),
106						h.Text("Salary"),
107					),
108					h.Th(
109						h.Class("px-4 py-2"),
110					),
111				),
112			),
113			h.TBody(
114				h.Class("divide-y divide-gray-200"),
115				h.List(records, func(record Record, index int) *h.Element {
116					return TableRow(&record, false)
117				}),
118			),
119		),
120	)
121}
122
123func TableRow(record *Record, editing bool) *h.Element {
124	recordId := fmt.Sprintf("record-%s", record.Id)
125
126	var Cell = func(name string, value string) *h.Element {
127		return h.Td(
128			h.Class(RowClasses, "h-[75px]"),
129			h.IfElse(
130				!editing,
131				h.Pf(
132					value,
133					h.Class("w-[125px]"),
134				),
135				h.Input(
136					"text",
137					h.Class(InputClasses),
138					h.Value(value),
139					h.Name(name),
140				),
141			),
142		)
143	}
144
145	return h.Tr(
146		h.If(
147			editing,
148			// this is important to make sure the inputs are included in the form submission
149			h.HxInclude("input"),
150		),
151		h.Id(recordId),
152		Cell("name", record.Name),
153		Cell("birthday", record.Birthday),
154		Cell("role", record.Role),
155		Cell("salary", record.Salary),
156		// Edit button
157		h.Td(
158			h.Button(
159				h.Class(ButtonClasses),
160				h.PostPartialWithQs(
161					h.Ternary(!editing, StartEditing, SaveEditing),
162					h.NewQs("id", record.Id),
163				),
164				h.Text(
165					h.Ternary(!editing, "Edit", "Save"),
166				),
167			),
168		),
169	)
170}