DurationField
Since 0.1.0-alpha.20Static server-side rendering: no circuit, no WebAssembly.
A length of time.
Usage
<DurationField @bind-Value="Model.Timeout" />
<DurationField @bind-Value="Model.Runtime" SmallestUnit="DurationUnit.Minutes" />
<DurationField @bind-Value="Model.Retention" LargestUnit="DurationUnit.Days" SmallestUnit="DurationUnit.Hours" Max="TimeSpan.FromDays(90)" />Units and limits
Use LargestUnit and SmallestUnit for the boxes it shows. Min and Max come from [Range], or set them on the field; the server checks them on submit.
Preview
Code
System.ComponentModel.DataAnnotations
<Form Model="Model" FormName="duration-field-limits" OnValidSubmit="Save" MaxWidth="24.Rem" Grow>
<DurationField @bind-Value="Model!.Timeout" Hint="From a second to an hour." />
<DurationField @bind-Value="Model!.Retention" LargestUnit="DurationUnit.Days" SmallestUnit="DurationUnit.Hours" Max="TimeSpan.FromDays(90)" Hint="Up to 90 days." />
<Row><Button Submit>Save settings</Button></Row>
if (_saved is { } saved)
{
<Alert Status="Status.Success">Saved: time out after saved.Timeout, keep for (saved.Retention?.ToString() ?? "no time").</Alert>
}
</Form>
{
[SupplyParameterFromForm(FormName = "duration-field-limits")]
private Settings? Model { get; set; }
// What was saved, not the fields: on an interactive page they follow typing.
private (TimeSpan Timeout, TimeSpan? Retention)? _saved;
protected override void OnInitialized() => Model ??= new();
private void Save() => _saved = (Model!.Timeout!.Value, Model.Retention);
public sealed class Settings
{
[Required, Range(typeof(TimeSpan), "00:00:01", "01:00:00", ErrorMessage = "Pick from a second to an hour.")]
public TimeSpan? Timeout { get; set; } = TimeSpan.FromSeconds(90);
public TimeSpan? Retention { get; set; }
}
}Steps, signs, sizes, read-only and disabled
Use Step for the increments of the smallest box. A negative Min shows a sign.
Preview
Code
<Form Model="Model" FormName="duration-field-states" MaxWidth="24.Rem" Grow>
<DurationField @bind-Value="Model!.Slot" Label="Quarter hours" SmallestUnit="DurationUnit.Minutes" Step="TimeSpan.FromMinutes(15)" />
<DurationField @bind-Value="Model!.Offset" Label="Clock offset" Min="TimeSpan.FromHours(-12)" Max="TimeSpan.FromHours(14)" SmallestUnit="DurationUnit.Minutes" />
<DurationField @bind-Value="Model!.Small" Label="Small" Size="ControlSize.Sm" />
<DurationField @bind-Value="Model!.Large" Label="Large" Size="ControlSize.Lg" />
<DurationField @bind-Value="Model!.Signed" Label="Signed length" ReadOnly Hint="Read-only: posted, but can't be changed." />
<DurationField @bind-Value="Model!.Renews" Label="Renews after" Disabled Hint="Disabled: not posted." />
<DurationField @bind-Value="Model!.Timeout" Label="Timeout" Clearable />
</Form>
{
[SupplyParameterFromForm(FormName = "duration-field-states")]
private Contract? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
public sealed class Contract
{
public TimeSpan? Timeout { get; set; } = TimeSpan.FromMinutes(90);
public TimeSpan Slot { get; set; } = TimeSpan.FromMinutes(45);
public TimeSpan Offset { get; set; } = TimeSpan.FromHours(-5);
public TimeSpan Small { get; set; } = new(1, 30, 0);
public TimeSpan Large { get; set; } = new(1, 30, 0);
public TimeSpan Signed { get; set; } = new(26, 0, 0);
public TimeSpan Renews { get; set; } = new(0, 45, 10);
}
}Details
A value past LargestUnit shows in that unit, so 26 hours shows 26 in Hours. Typing 90 in Minutes becomes 1 hour and 30 minutes when the box is left. A value has whole seconds: anything finer is dropped when it posts, and so is anything under SmallestUnit once a box is edited.
Mode support
| Feature | Static | Interactive |
|---|---|---|
| A number box per unit, days to seconds, posted as one value | Yes | Yes |
| Min and Max checked on the server | Yes | Yes |
| Binds TimeSpan, with a sign when Min is negative | Yes | Yes |
Static: static server-side rendering, with no circuit and no WebAssembly. Interactive: Server, WebAssembly or Auto.
Without JavaScript
Every page starts as plain HTML: before IzzyBlazor's script loads on a static page, while an interactive page prerenders, and with JavaScript off. With JavaScript off, one text box takes the length as hh:mm:ss, or d.hh:mm:ss with days, in place of a box per unit.
Accessibility
- The boxes are a
groupnamed by the label, each a native numberinputnamed by its unit, one tab stop each. Up and Down arrows change a box. - A sign shows only when
Minis negative or the value is, as a toggle button named "Negative". - The hint and errors are linked to the group, and label, hint and errors work as in
TextField.
Parameters
| Prop | Type | Default |
|---|---|---|
ClearableA button beside the boxes that empties them, for a nullable value, there while it holds something. | bool | false |
ReadOnlyMakes the field read-only: it can be focused, and it still posts. | bool | false |
LargestUnitThe largest unit with a box. | DurationUnit | DurationUnit.Hours |
SmallestUnitThe smallest unit with a box. | DurationUnit | DurationUnit.Seconds |
MinThe shortest length, checked on the server. | TimeSpan? | computed |
MaxThe longest length, checked on the server. | TimeSpan? | computed |
StepThe step of SmallestUnit's box, such as 15 minutes: whole units of it, under the next unit up. | TimeSpan? | |
@bind-ValueThe value, bound with @bind-Value. | TValue | |
DisplayNameThe field's name in validation messages from the input itself, such as a value that can't be parsed. | string? |
Plus 26 field props.
Full APISee also
- TimeField: a time of day, in the browser's own input, with a list of times to choose from.
- NumberField: a number input with stepper buttons.
- Form: posts on static pages, validates live on interactive ones.