NetLife Guru

Open source Go packages for fast, maintainable web systems. Built with a documentation-first approach.

Product
OverviewGolang packagesNews
Documentation
DocumentationGo LoggerGo RouterGo DB Form
Company
OverviewContactNewsGitHub
Community / Support
Supportinfo@netlife.guru
© 2026 NetLife Guru. All rights reserved.
GitHubinfo@netlife.guru
NetLife GuruNetLife GuruNetLife Guru
NetLife GuruNetLife GuruNetLife Guru
OverviewDocumentationNewsSupportContact

Golang packages

About
Conditional ValidationConditional RulesConditional When
Form ValidatorConditional Validation

Conditional Rules

Learn how to use NLG Form conditional rule helpers for required-if, prohibited-if, required-with, and required-without validation flows.

Conditional rule helpers provide shortcuts for common conditional validation patterns.

They are built on top of conditional.When, but make frequent validation cases easier to read and reuse.

Use conditional rule helpers when validation depends on other fields in the same request.

Common Use Cases

Conditional rules are commonly used for:

  • company-only fields
  • country-specific billing fields
  • admin-only notes
  • contact method validation
  • address-dependent fields
  • backup contact information
  • onboarding flows
  • profile completion
  • dynamic form sections

TL;DR

HelperDescription
conditional.RequiredIfStr(field, cond)Requires a string field when cond returns true
conditional.RequiredIfStrWithCode(field, cond, code)Same as RequiredIfStr with a custom error code
conditional.ProhibitedIfStr(field, cond)Forbids a non-blank string value when cond returns true
conditional.ProhibitedIfStrWithCode(field, cond, code)Same as ProhibitedIfStr with a custom error code
conditional.RequiredWithAnyStr(field, others...)Requires a string field when any other field is non-blank
conditional.RequiredWithAnyStrWithCode(field, code, others...)Same as RequiredWithAnyStr with a custom error code
conditional.RequiredWithoutAnyStr(field, others...)Requires a string field when any other field is blank
conditional.RequiredWithoutAnyStrWithCode(field, code, others...)Same as RequiredWithoutAnyStr with a custom error code

Defining Conditional Fields

Conditional validation starts with regular typed string fields.

ConditionalRulesForm := struct {
	AccountType form.StringField[ConditionalRulesRequest]
	CompanyName form.StringField[ConditionalRulesRequest]
	Country     form.StringField[ConditionalRulesRequest]
	VatNumber   form.StringField[ConditionalRulesRequest]
	Role        form.StringField[ConditionalRulesRequest]
	AdminNote   form.StringField[ConditionalRulesRequest]
}{
	AccountType: form.Str[ConditionalRulesRequest]("account_type", func(r *ConditionalRulesRequest) string {
		return r.AccountType
	}),
	CompanyName: form.Str[ConditionalRulesRequest]("company_name", func(r *ConditionalRulesRequest) string {
		return r.CompanyName
	}),
	Country: form.Str[ConditionalRulesRequest]("country", func(r *ConditionalRulesRequest) string {
		return r.Country
	}),
	VatNumber: form.Str[ConditionalRulesRequest]("vat_number", func(r *ConditionalRulesRequest) string {
		return r.VatNumber
	}),
	Role: form.Str[ConditionalRulesRequest]("role", func(r *ConditionalRulesRequest) string {
		return r.Role
	}),
	AdminNote: form.Str[ConditionalRulesRequest]("admin_note", func(r *ConditionalRulesRequest) string {
		return r.AdminNote
	}),
}

Applying Conditional Rules

Conditional helpers attach validation behavior to fields based on runtime values.

return form.Schema[ConditionalRulesRequest]{
	conditional.RequiredIfStr(
		ConditionalRulesForm.CompanyName,
		func(r *ConditionalRulesRequest) bool {
			return r.AccountType == "company"
		},
	),

	conditional.RequiredIfStrWithCode(
		ConditionalRulesForm.VatNumber,
		func(r *ConditionalRulesRequest) bool {
			return r.Country == "SK"
		},
		CodeVatNumberRequired,
	),

	conditional.ProhibitedIfStr(
		ConditionalRulesForm.AdminNote,
		func(r *ConditionalRulesRequest) bool {
			return r.Role != "admin"
		},
	),
}

Rule Examples

RequiredIfStr

Requires a string field when the condition returns true.

conditional.RequiredIfStr(
	ConditionalRulesForm.CompanyName,
	func(r *ConditionalRulesRequest) bool {
		return r.AccountType == "company"
	},
)

This is useful when one field becomes mandatory based on another field.


RequiredIfStrWithCode

Requires a string field when the condition returns true and returns a custom validation code.

const CodeVatNumberRequired = form.Code("vat_number_required")

conditional.RequiredIfStrWithCode(
	ConditionalRulesForm.VatNumber,
	func(r *ConditionalRulesRequest) bool {
		return r.Country == "SK"
	},
	CodeVatNumberRequired,
)

This is useful for country-specific, account-specific, or workflow-specific validation.


ProhibitedIfStr

Forbids a non-blank string value when the condition returns true.

conditional.ProhibitedIfStr(
	ConditionalRulesForm.AdminNote,
	func(r *ConditionalRulesRequest) bool {
		return r.Role != "admin"
	},
)

Validation behavior:

ConditionField valueResult
falseany valueskipped
true""valid
true"secret note"invalid

ProhibitedIfStrWithCode

Forbids a non-blank string value when the condition returns true and returns a custom validation code.

const CodeInternalNoteBlocked = form.Code("internal_note_blocked")

conditional.ProhibitedIfStrWithCode(
	ConditionalRulesForm.InternalNote,
	func(r *ConditionalRulesRequest) bool {
		return r.UserType == "external"
	},
	CodeInternalNoteBlocked,
)

This is useful for protecting internal-only fields from public or external input.


RequiredWithAnyStr

Requires a field when any of the referenced fields is non-blank.

conditional.RequiredWithAnyStr(
	ConditionalRulesForm.Email,
	ConditionalRulesForm.Phone,
)

This means:

if phone is filled, email is required

Typical use cases:

  • contact method pairs
  • dependent address fields
  • partially completed form sections

RequiredWithAnyStrWithCode

Requires a field when any referenced field is non-blank and returns a custom validation code.

const CodeContactRequired = form.Code("contact_required")

conditional.RequiredWithAnyStrWithCode(
	ConditionalRulesForm.ContactName,
	CodeContactRequired,
	ConditionalRulesForm.Address,
	ConditionalRulesForm.City,
)

This means:

if address or city is filled, contact_name is required

RequiredWithoutAnyStr

Requires a field when any referenced field is blank.

conditional.RequiredWithoutAnyStr(
	ConditionalRulesForm.Phone,
	ConditionalRulesForm.Email,
)

This means:

if email is blank, phone is required

Typical use cases:

  • fallback contact fields
  • at-least-one contact method
  • alternative input paths

RequiredWithoutAnyStrWithCode

Requires a field when any referenced field is blank and returns a custom validation code.

const CodeBackupRequired = form.Code("backup_required")

conditional.RequiredWithoutAnyStrWithCode(
	ConditionalRulesForm.BackupEmail,
	CodeBackupRequired,
	ConditionalRulesForm.BackupPhone,
)

This means:

if backup_phone is blank, backup_email is required

Complete Example

schema.go

package main

import (
	"github.com/netlifeguru/form"
	"github.com/netlifeguru/form/conditional"
)

const (
	CodeVatNumberRequired  = form.Code("vat_number_required")
	CodeInternalNoteBlocked = form.Code("internal_note_blocked")
	CodeContactRequired    = form.Code("contact_required")
	CodeBackupRequired     = form.Code("backup_required")
)

type ConditionalRulesRequest struct {
	AccountType string `json:"account_type"`
	CompanyName string `json:"company_name"`

	Country   string `json:"country"`
	VatNumber string `json:"vat_number"`

	Role         string `json:"role"`
	AdminNote    string `json:"admin_note"`
	UserType      string `json:"user_type"`
	InternalNote string `json:"internal_note"`

	Phone       string `json:"phone"`
	Email       string `json:"email"`
	Address     string `json:"address"`
	City        string `json:"city"`
	ContactName string `json:"contact_name"`

	BackupEmail string `json:"backup_email"`
	BackupPhone string `json:"backup_phone"`
}

func ConditionalRulesSchema() form.Schema[ConditionalRulesRequest] {
	ConditionalRulesForm := struct {
		AccountType form.StringField[ConditionalRulesRequest]
		CompanyName form.StringField[ConditionalRulesRequest]
		Country     form.StringField[ConditionalRulesRequest]
		VatNumber   form.StringField[ConditionalRulesRequest]

		Role         form.StringField[ConditionalRulesRequest]
		AdminNote    form.StringField[ConditionalRulesRequest]
		UserType      form.StringField[ConditionalRulesRequest]
		InternalNote form.StringField[ConditionalRulesRequest]

		Phone       form.StringField[ConditionalRulesRequest]
		Email       form.StringField[ConditionalRulesRequest]
		Address     form.StringField[ConditionalRulesRequest]
		City        form.StringField[ConditionalRulesRequest]
		ContactName form.StringField[ConditionalRulesRequest]

		BackupEmail form.StringField[ConditionalRulesRequest]
		BackupPhone form.StringField[ConditionalRulesRequest]
	}{
		AccountType: form.Str[ConditionalRulesRequest]("account_type", func(r *ConditionalRulesRequest) string {
			return r.AccountType
		}),
		CompanyName: form.Str[ConditionalRulesRequest]("company_name", func(r *ConditionalRulesRequest) string {
			return r.CompanyName
		}),
		Country: form.Str[ConditionalRulesRequest]("country", func(r *ConditionalRulesRequest) string {
			return r.Country
		}),
		VatNumber: form.Str[ConditionalRulesRequest]("vat_number", func(r *ConditionalRulesRequest) string {
			return r.VatNumber
		}),

		Role: form.Str[ConditionalRulesRequest]("role", func(r *ConditionalRulesRequest) string {
			return r.Role
		}),
		AdminNote: form.Str[ConditionalRulesRequest]("admin_note", func(r *ConditionalRulesRequest) string {
			return r.AdminNote
		}),
		UserType: form.Str[ConditionalRulesRequest]("user_type", func(r *ConditionalRulesRequest) string {
			return r.UserType
		}),
		InternalNote: form.Str[ConditionalRulesRequest]("internal_note", func(r *ConditionalRulesRequest) string {
			return r.InternalNote
		}),

		Phone: form.Str[ConditionalRulesRequest]("phone", func(r *ConditionalRulesRequest) string {
			return r.Phone
		}),
		Email: form.Str[ConditionalRulesRequest]("email", func(r *ConditionalRulesRequest) string {
			return r.Email
		}),
		Address: form.Str[ConditionalRulesRequest]("address", func(r *ConditionalRulesRequest) string {
			return r.Address
		}),
		City: form.Str[ConditionalRulesRequest]("city", func(r *ConditionalRulesRequest) string {
			return r.City
		}),
		ContactName: form.Str[ConditionalRulesRequest]("contact_name", func(r *ConditionalRulesRequest) string {
			return r.ContactName
		}),

		BackupEmail: form.Str[ConditionalRulesRequest]("backup_email", func(r *ConditionalRulesRequest) string {
			return r.BackupEmail
		}),
		BackupPhone: form.Str[ConditionalRulesRequest]("backup_phone", func(r *ConditionalRulesRequest) string {
			return r.BackupPhone
		}),
	}

	return form.Schema[ConditionalRulesRequest]{
		conditional.RequiredIfStr(
			ConditionalRulesForm.CompanyName,
			func(r *ConditionalRulesRequest) bool {
				return r.AccountType == "company"
			},
		),

		conditional.RequiredIfStrWithCode(
			ConditionalRulesForm.VatNumber,
			func(r *ConditionalRulesRequest) bool {
				return r.Country == "SK"
			},
			CodeVatNumberRequired,
		),

		conditional.ProhibitedIfStr(
			ConditionalRulesForm.AdminNote,
			func(r *ConditionalRulesRequest) bool {
				return r.Role != "admin"
			},
		),

		conditional.ProhibitedIfStrWithCode(
			ConditionalRulesForm.InternalNote,
			func(r *ConditionalRulesRequest) bool {
				return r.UserType == "external"
			},
			CodeInternalNoteBlocked,
		),

		conditional.RequiredWithAnyStr(
			ConditionalRulesForm.Email,
			ConditionalRulesForm.Phone,
		),

		conditional.RequiredWithAnyStrWithCode(
			ConditionalRulesForm.ContactName,
			CodeContactRequired,
			ConditionalRulesForm.Address,
			ConditionalRulesForm.City,
		),

		conditional.RequiredWithoutAnyStr(
			ConditionalRulesForm.Phone,
			ConditionalRulesForm.Email,
		),

		conditional.RequiredWithoutAnyStrWithCode(
			ConditionalRulesForm.BackupEmail,
			CodeBackupRequired,
			ConditionalRulesForm.BackupPhone,
		),
	}
}

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-rules", "POST", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
		var in ConditionalRulesRequest

		if !httpform.BindAndValidate(w, req, &in, ConditionalRulesSchema(), 1<<20) {
			fmt.Println("conditional rules validation failed")
			return
		}

		fmt.Println("conditional rules validation passed:", in)

		w.Header().Set("Content-Type", "application/json")

		_ = json.NewEncoder(w).Encode(map[string]any{
			"message": "conditional rules validation passed",
			"data":    in,
		})
	})

	validPayload := map[string]any{
		"account_type": "company",
		"company_name": "Acme s.r.o.",
		"country":      "SK",
		"vat_number":   "SK1234567890",

		"role":          "user",
		"admin_note":    "",
		"user_type":     "external",
		"internal_note": "",

		"phone":        "+421900123456",
		"email":        "john@example.com",
		"address":      "Main Street 1",
		"city":         "",
		"contact_name": "John Doe",

		"backup_email": "backup@example.com",
		"backup_phone": "",
	}

	invalidPayload := map[string]any{
		"account_type": "company",
		"company_name": "",
		"country":      "SK",
		"vat_number":   "",

		"role":          "user",
		"admin_note":    "internal only",
		"user_type":     "external",
		"internal_note": "secret note",

		"phone":        "+421900123456",
		"email":        "",
		"address":      "Main Street 1",
		"city":         "",
		"contact_name": "",

		"backup_email": "",
		"backup_phone": "",
	}

	fmt.Println("\n--- Valid request ---")
	form.SendTestPost(":8080/conditional-rules", validPayload)

	fmt.Println("\n--- Invalid request ---")
	form.SendTestPost(":8080/conditional-rules", invalidPayload)

	if err := r.ListenAndServe(8080); err != nil {
		slog.Error("failed to start server", "error", err)
		os.Exit(1)
	}
}

Notes

  • Conditional rule helpers are shortcuts for common When patterns.
  • Conditions receive the full request structure.
  • String conditional helpers use blank-string behavior based on trimmed string values.
  • Use RequiredIfStr when a field becomes required in a specific state.
  • Use ProhibitedIfStr when a field must stay empty in a specific state.
  • Use RequiredWithAnyStr when one field depends on another field being filled.
  • Use RequiredWithoutAnyStr when one field is required as a fallback.
  • Use When directly for advanced rule composition or multiple nested rules.

Conditional Validation

Learn how conditional validation works in NLG Form using conditional rules, runtime predicates, When helpers, and reusable validation pipelines.

Conditional When

Learn how to use conditional.When in NLG Form to run validation rules only when custom runtime predicates match.

On this page

Common Use CasesTL;DRDefining Conditional FieldsApplying Conditional RulesRule ExamplesRequiredIfStrRequiredIfStrWithCodeProhibitedIfStrProhibitedIfStrWithCodeRequiredWithAnyStrRequiredWithAnyStrWithCodeRequiredWithoutAnyStrRequiredWithoutAnyStrWithCodeComplete Exampleschema.gomain.goNotes