Click To Edit
| First Name | John |
|---|---|
| Last Name | Doe |
| john@example.com |
Show a record read-only, then swap the same region for an edit form on demand — no
client state, no separate edit route. An Editing boolean on the server state picks
the branch the template renders; Save commits the fields and flips it back,
Cancel flips it back untouched.
The whole pattern is one {{if .Editing}} branch — view mode renders a table plus an
Edit button; edit mode renders the form with Save/Cancel. Each button's name is the
action it triggers.
{{define "content"}}
<article>
<h3>Click To Edit</h3>
{{if .Editing}}
<form method="POST">
<label>First Name
<input name="firstName" value="{{.FirstName}}" required>
</label>
<label>Last Name
<input name="lastName" value="{{.LastName}}" required>
</label>
<label>Email
<input name="email" type="email" value="{{.Email}}" required>
</label>
<fieldset role="group">
<button name="save">Save</button>
<button name="cancel" class="secondary">Cancel</button>
</fieldset>
</form>
{{else}}
<table>
<tbody>
<tr><th>First Name</th><td>{{.FirstName}}</td></tr>
<tr><th>Last Name</th><td>{{.LastName}}</td></tr>
<tr><th>Email</th><td>{{.Email}}</td></tr>
</tbody>
</table>
<form method="POST">
<button name="edit" class="outline">Edit</button>
</form>
{{end}}
</article>
{{end}}
Three tiny actions toggle Editing; Save also reads the submitted fields.
type ClickToEditController struct{}
func (c *ClickToEditController) Edit(state ClickToEditState, ctx *livetemplate.Context) (ClickToEditState, error) {
state.Editing = true
return state, nil
}
func (c *ClickToEditController) Save(state ClickToEditState, ctx *livetemplate.Context) (ClickToEditState, error) {
state.FirstName = ctx.GetString("firstName")
state.LastName = ctx.GetString("lastName")
state.Email = ctx.GetString("email")
state.Editing = false
return state, nil
}
func (c *ClickToEditController) Cancel(state ClickToEditState, ctx *livetemplate.Context) (ClickToEditState, error) {
state.Editing = false
return state, nil
}
func clickToEditHandler() http.Handler {
tmpl := newLayoutTmpl("templates/layout.tmpl", "templates/forms/click-to-edit.tmpl")
return tmpl.Handle(&ClickToEditController{}, livetemplate.AsState(&ClickToEditState{
Title: "Click To Edit",
Category: "Forms & Editing",
FirstName: "John",
LastName: "Doe",
Email: "john@example.com",
}))
}
type ClickToEditState struct {
Title string
Category string
FirstName string
LastName string
Email string
Editing bool
}
Reach for Edit Row instead when many rows in a table each need independent inline editing.