Form ValidatorConditional Validation
Conditional When
Learn how to use conditional.When in NLG Form to run validation rules only when custom runtime predicates match.
conditional.When is the low-level primitive for conditional validation.
It allows one or more validation rules to run only when a custom predicate returns true.
Use When when predefined conditional helpers are not expressive enough.
TL;DR
| Helper | Description |
|---|---|
conditional.When(cond, rules...) | Runs nested rules only when cond returns true |
Basic Usage
conditional.When(
func(r *Request) bool {
return r.AccountType == "business"
},
rules.Required(Form.CompanyName),
)If the condition is false, validation is skipped.
If the condition is true, all nested rules are executed.
Common Use Cases
- business account validation
- password change flows
- billing sections
- role-based validation
- feature-specific fields
- multi-step forms
- PATCH APIs
- advanced business rules
Complete Example
schema.go
package main
import (
"github.com/netlifeguru/form"
"github.com/netlifeguru/form/conditional"
"github.com/netlifeguru/form/rules"
)
const (
CodeCompanyRequired = form.Code("company_required")
CodePasswordMinLen = form.Code("password_min_len")
)
type ConditionalWhenRequest struct {
AccountType string `json:"account_type"`
CompanyName string `json:"company_name"`
ChangePassword bool `json:"change_password"`
NewPassword string `json:"new_password"`
}
func ConditionalWhenSchema() form.Schema[ConditionalWhenRequest] {
ConditionalWhenForm := struct {
AccountType form.StringField[ConditionalWhenRequest]
CompanyName form.StringField[ConditionalWhenRequest]
ChangePassword form.BoolField[ConditionalWhenRequest]
NewPassword form.StringField[ConditionalWhenRequest]
}{
AccountType: form.Str[ConditionalWhenRequest]("account_type", func(r *ConditionalWhenRequest) string {
return r.AccountType
}),
CompanyName: form.Str[ConditionalWhenRequest]("company_name", func(r *ConditionalWhenRequest) string {
return r.CompanyName
}),
ChangePassword: form.Bool[ConditionalWhenRequest]("change_password", func(r *ConditionalWhenRequest) bool {
return r.ChangePassword
}),
NewPassword: form.Str[ConditionalWhenRequest]("new_password", func(r *ConditionalWhenRequest) string {
return r.NewPassword
}),
}
return form.Schema[ConditionalWhenRequest]{
conditional.When(
func(r *ConditionalWhenRequest) bool {
return r.AccountType == "business"
},
rules.RequiredWithCode(ConditionalWhenForm.CompanyName, CodeCompanyRequired),
),
conditional.When(
func(r *ConditionalWhenRequest) bool {
return r.ChangePassword
},
rules.Required(ConditionalWhenForm.NewPassword),
rules.MinLenWithCode(ConditionalWhenForm.NewPassword, 8, CodePasswordMinLen),
),
}
}main.go
package main
import (
"encoding/json"
"fmt"
"log/slog"
"net/http"
"os"
"github.com/netlifeguru/form"
"github.com/netlifeguru/form/httpform"
"github.com/netlifeguru/router"
)
func main() {
r := router.New()
r.HandleFunc("/conditional-when", "POST", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
var in ConditionalWhenRequest
if !httpform.BindAndValidate(w, req, &in, ConditionalWhenSchema(), 1<<20) {
fmt.Println("conditional when validation failed")
return
}
fmt.Println("conditional when validation passed:", in)
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
"message": "conditional when validation passed",
"data": in,
})
})
validPayload := map[string]any{
"account_type": "business",
"company_name": "Acme s.r.o.",
"change_password": true,
"new_password": "secret123",
}
invalidPayload := map[string]any{
"account_type": "business",
"company_name": "",
"change_password": true,
"new_password": "short",
}
skippedPayload := map[string]any{
"account_type": "personal",
"company_name": "",
"change_password": false,
"new_password": "",
}
fmt.Println("\n--- Valid request ---")
form.SendTestPost(":8080/conditional-when", validPayload)
fmt.Println("\n--- Invalid request ---")
form.SendTestPost(":8080/conditional-when", invalidPayload)
fmt.Println("\n--- Skipped conditional validation request ---")
form.SendTestPost(":8080/conditional-when", skippedPayload)
if err := r.ListenAndServe(8080); err != nil {
slog.Error("failed to start server", "error", err)
os.Exit(1)
}
}Validation Flow
condition is false
↓
nested validation skippedcondition is true
↓
nested rules executedNotes
Whenis the most flexible conditional validation primitive.- Conditions receive the full request structure.
- A single
Whenblock can contain multiple nested rules. - Use
Whenfor custom business logic. - Use convenience helpers such as
RequiredIfStrfor common conditional cases. - Conditional validation remains explicit and transport-independent.