Edit Row
| Name | ||
|---|---|---|
| Joe Smith | joe@smith.org | |
| Angie MacDowell | angie@macdowell.org | |
| Fuqua Tarkenton | fuqua@tarkenton.org | |
| Kim Yee | kim@yee.org |
A table where any single row flips into an edit form in place. The server tracks one
EditingID; the row whose ID matches renders inputs, every other row stays read-only.
Each Edit/Save button carries its row ID in the button value, so the handler knows
which record to act on.
{{if eq $.EditingID .ID}} chooses the edit form vs the read-only cells per row.
{{define "content"}}
<article>
<h3>Edit Row</h3>
<table>
<thead><tr><th>Name</th><th>Email</th><th></th></tr></thead>
<tbody>
{{range .Contacts}}
<tr data-key="{{.ID}}">
{{if eq $.EditingID .ID}}
<td colspan="3">
<form method="POST" class="inline">
<fieldset role="group">
<input name="name" value="{{.Name}}" aria-label="Name">
<input name="email" value="{{.Email}}" aria-label="Email">
<button name="save" value="{{.ID}}" class="compact">Save</button>
<button name="cancel" class="compact secondary">Cancel</button>
</fieldset>
</form>
</td>
{{else}}
<td>{{.Name}}</td>
<td>{{.Email}}</td>
<td>
<form method="POST" class="inline">
<button name="edit" value="{{.ID}}" class="compact secondary outline">Edit</button>
</form>
</td>
{{end}}
</tr>
{{end}}
</tbody>
</table>
</article>
{{end}}
Edit records which row is open (value = row ID); Save writes the fields back to
that contact and clears EditingID.
type EditRowController struct{}
func (c *EditRowController) Edit(state EditRowState, ctx *livetemplate.Context) (EditRowState, error) {
// Edit/Save buttons send their ID via `value` attribute — see
// docs/references/progressive-complexity-reference.md.
state.EditingID = ctx.GetString("value")
return state, nil
}
func (c *EditRowController) Save(state EditRowState, ctx *livetemplate.Context) (EditRowState, error) {
id := ctx.GetString("value")
for i, contact := range state.Contacts {
if contact.ID == id {
state.Contacts[i].Name = ctx.GetString("name")
state.Contacts[i].Email = ctx.GetString("email")
break
}
}
state.EditingID = ""
return state, nil
}
func (c *EditRowController) Cancel(state EditRowState, ctx *livetemplate.Context) (EditRowState, error) {
state.EditingID = ""
return state, nil
}
func editRowHandler() http.Handler {
tmpl := newLayoutTmpl("templates/layout.tmpl", "templates/forms/edit-row.tmpl")
return tmpl.Handle(&EditRowController{}, livetemplate.AsState(&EditRowState{
Title: "Edit Row",
Category: "Forms & Editing",
Contacts: sampleContacts(),
}))
}
type EditRowState struct {
Title string
Category string
Contacts []Contact
EditingID string
}
EditingID keeps it simple — no per-row flags.For a single standalone record, Click to Edit is the simpler shape.