Async & cascading options
Options do not have to be baked into the schema. OptionsFrom loads them on demand and
declares which fields they depend on — pick a country and the city list reloads (dropping any
selection that no longer exists). The company field below is conditionally required and
clears itself when it is hidden, so an abandoned branch never reaches your model.
View source
@page "/cascading"
@inject DemoDirectory Directory
<BormView State="_state" OnValidSubmit="HandleSubmit" SubmitText="Save address" />
@code {
private readonly DeliveryAddress _model = new();
private BormState _state = default!;
protected override void OnInitialized()
{
var schema = BormBuilder.For<DeliveryAddress>()
.Title("Where should we deliver?")
.Field(x => x.Country, f => f
.Required()
.Options(DemoDirectory.Countries.ToArray())
.Autocomplete("country"))
.Field(x => x.City, f => f
.Required()
// Loaded on demand, and reloaded whenever Country changes.
.OptionsFrom(
load: async ctx => await Directory.GetCitiesAsync(ctx.Value("Country") as string, ctx.CancellationToken),
value: city => city,
label: city => city,
dependsOn: nameof(DeliveryAddress.Country))
.Placeholder("Pick a country first"))
.Field(x => x.IsBusiness)
.Field(x => x.CompanyName, f => f
.VisibleWhen(nameof(DeliveryAddress.IsBusiness), BormConditionOperator.IsTrue)
.RequiredWhen(nameof(DeliveryAddress.IsBusiness), BormConditionOperator.IsTrue)
.ClearOnHide())
.Field(x => x.Notes, f => f.AsTextArea(2))
.Build();
_state = new BormState(schema, new BormModelDataAccessor(_model));
_state.StateChanged += OnStateChanged;
}
}