Per-row conditions
A condition written on a repeater's item template means this row. Change one contact's
method and only that contact's fields switch — the rest of the list is untouched, and the row's
chosen field is the only one that has to be filled in. Paths are resolved against the object
that owns the field first, exactly as a computed value's dependencies are, so
"Kind" inside a row is that row's Kind.
View source
var schema = BormBuilder.For<ContactSheet>()
.Title("Contact sheet")
.Field(x => x.Name, f => f.Required())
.Array(x => x.Contacts, row => row
.Field(c => c.Kind, f => f
.AsRadio()
.Options(("email", "Email"), ("phone", "Phone"), ("post", "Post")))
// "Kind" here is *this row's* Kind. Every row evaluates its own answer, so switching one
// contact to Phone does not reshape the others.
.Field(c => c.Email, f => f
.AsEmail()
.VisibleWhen("Kind", BormConditionOperator.Equals, "email")
.RequiredWhen("Kind", BormConditionOperator.Equals, "email")
.ClearOnHide())
.Field(c => c.Phone, f => f
.AsTel()
.VisibleWhen("Kind", BormConditionOperator.Equals, "phone")
.RequiredWhen("Kind", BormConditionOperator.Equals, "phone")
.ClearOnHide())
.Field(c => c.Address, f => f
.AsTextArea(2)
.VisibleWhen("Kind", BormConditionOperator.Equals, "post")
.RequiredWhen("Kind", BormConditionOperator.Equals, "post")
.ClearOnHide()),
// A row starts on Email, because the template declares a default — and defaults now reach
// every row the user adds, not only the ones the form was created with.
f => f.Items(min: 1, message: "Add at least one contact.")
.SeedMinItems() // open with the row the schema requires, not with an error
.Attr("itemNoun", "contact")
.Attr("duplicable", true)) // "add another one like that"
.Build();