Apariencia
Caso de uso: opciones dependientes
Anterior: formulario · Casos de uso · Siguiente: reutilización
Usa Options cuando las opciones de un campo dependen de otro valor, como ciudades por país. La sesión carga datos y descarta respuestas antiguas; la UI decide qué hacer con la selección actual.
Flujo
text
CountryId cambia
↓ EnsureLoadedAsync
↓ compara DependsOn + contexto
├─ sin cambios → reutiliza carga
└─ con cambios → cancela carga anterior
↓ consulta ciudades
↓ Ready / Failed / CanceledEjemplo completo
csharp
using Greencore.platform.validators;
var definition = Options.For<AddressDraft, AddressContext>()
.Field(x => x.CityId)
.Load<CityOption>((address, context, token) =>
context.Cities.GetByCountryAsync(address.CountryId, token))
.DependsOn(x => x.CountryId);
using var session = definition.CreateSession();
session.Changed += snapshot =>
{
if (snapshot.State == DataState.Ready)
Console.WriteLine($"Opciones publicadas: {snapshot.Value!.Count}");
};
var address = new AddressDraft(CountryId: 1, CityId: null);
var context = new AddressContext(new CityRepository());
var first = await session.EnsureLoadedAsync(address, context);
foreach (var city in first.Value!)
Console.WriteLine(city.Name);
// Mismas dependencias y contexto: reutiliza la operación anterior.
var reused = await session.EnsureLoadedAsync(address with { CityId = 10 }, context);
// Fuerza una consulta aunque las dependencias no hayan cambiado.
var refreshed = await session.ReloadAsync(address, context);
public sealed record AddressDraft(int CountryId, int? CityId);
public sealed record CityOption(int Id, string Name);
public sealed record AddressContext(ICityRepository Cities);
public interface ICityRepository
{
ValueTask<IReadOnlyList<CityOption>> GetByCountryAsync(int countryId, CancellationToken cancellationToken);
}
public sealed class CityRepository : ICityRepository
{
public ValueTask<IReadOnlyList<CityOption>> GetByCountryAsync(int countryId, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
IReadOnlyList<CityOption> result = countryId == 1
? [new(10, "La Paz"), new(11, "Cochabamba")]
: [new(20, "Lima")];
return ValueTask.FromResult(result);
}
}Decisiones importantes
DependsOncompara valores; no se suscribe a cambios del modelo.- Declara toda propiedad que afecte al loader.
EnsureLoadedAsyncreutiliza cargas equivalentes.ReloadAsyncfuerza una nueva carga.- Un fallo permite reintentar.
- Durante
Pendingno se conservan opciones antiguas. - La sesión no borra
CityId; esa decisión pertenece a la UI. - Un plan de validación debe comprobar por separado que la ciudad seleccionada sea válida.