Details
Displays labelled read-only values, such as the fields of a record or its audit information
<sa-details columns="2">
<sa-display-field asp-for="Reference" />
<sa-display-field asp-for="Status" />
<sa-display-field asp-for="LeadTraveller" />
<sa-display-field asp-for="Email" />
<sa-display-field asp-for="Destination" href="#destination-@Model.DestinationId" />
<sa-display-field asp-for="Departure" />
<sa-display-field asp-for="Party" />
<sa-display-field asp-for="Total" />
<sa-display-field asp-for="PromoCode" />
</sa-details>Usage
A details list is composed of <sa-details> wrapping one <sa-display-field> per value. Bind each field to a model property with asp-for: the label comes from the property's [Display] name, and the value is formatted from the property's metadata.
<sa-details columns="...">
<sa-display-field asp-for="..." />
<sa-display-field asp-for="..." />
</sa-details>Inside <sa-details> the fields render as a description list, with each label in a <dt> and each value in a <dd>. A <sa-display-field> can also be used on its own, for example among the inputs of a form; it then renders <div> elements instead.
Examples
Columns and spans
Set columns to lay the fields out in a grid. The columns respond to the width of the list rather than the viewport, so the same markup works in a page, a card or a side panel. columns applies once the list is at least 40rem wide, and the list uses one column below that. Use columns-sm, columns-md and columns-lg to set the number of columns at 30rem, 40rem and 56rem; a width without a value uses the value of the next smaller width.
Set column-span on a field to span several columns, or column-span-full to span all of them. column-span-sm, column-span-md and column-span-lg set the span at each width in the same way, and a span is limited to the number of columns at each width.
<sa-details columns="3" columns-sm="2" columns-lg="4">
<sa-display-field asp-for="Reference" />
<sa-display-field asp-for="LeadTraveller" />
<sa-display-field asp-for="Email" column-span="2" />
<sa-display-field asp-for="Departure" />
<sa-display-field asp-for="Return" />
<sa-display-field asp-for="Cabin" />
<sa-display-field asp-for="Party" />
<sa-display-field asp-for="Notes" column-span-full="true" column-span-lg="3" />
<sa-display-field asp-for="Total" />
</sa-details>Horizontal
Set orientation to FieldOrientation.Horizontal to place each label beside its value. Set it on <sa-details> for every field, or on a single <sa-display-field>.
<sa-details orientation="FieldOrientation.Horizontal">
<sa-display-field asp-for="Reference" />
<sa-display-field asp-for="Status" />
<sa-display-field asp-for="LeadTraveller" />
<sa-display-field asp-for="Email" />
<sa-display-field asp-for="Departure" />
<sa-display-field asp-for="Total" />
</sa-details>Divided
Set variant to DetailsVariant.Divided to separate the fields with rules. It suits a short horizontal list, such as audit information.
<sa-details variant="DetailsVariant.Divided" orientation="FieldOrientation.Horizontal">
<sa-display-field asp-for="CreatedAt" secondary="by @Model.CreatedBy" />
<sa-display-field asp-for="UpdatedAt" secondary="by @Model.UpdatedBy" />
<sa-display-field asp-for="Version" />
<sa-display-field asp-for="ArchivedAt" />
</sa-details>Responsive
Set orientation to FieldOrientation.Responsive to stack each label above its value in a narrow list, and place it beside the value once the list is at least 32rem wide.
<sa-details orientation="FieldOrientation.Responsive">
<sa-display-field asp-for="LeadTraveller" />
<sa-display-field asp-for="Destination" />
<sa-display-field asp-for="Departure" />
<sa-display-field asp-for="Party" />
</sa-details>Empty values
A null value, a blank string or an empty collection shows a dash in a muted color. Set empty-text to show different text, or set NullDisplayText in the property's [DisplayFormat] attribute to use the same text wherever the property is displayed. Zero and false are values, not empty ones.
<sa-details columns="2">
@* A dash by default *@
<sa-display-field asp-for="PromoCode" />
@* [DisplayFormat(NullDisplayText = "None")] *@
<sa-display-field asp-for="DietaryNeeds" />
<sa-display-field asp-for="ArchivedAt" empty-text="Not archived" />
@* Zero and false are values *@
<sa-display-field asp-for="Infants" />
</sa-details>Value types
Values are formatted from the property's metadata:
- The
formatattribute, or else theDataFormatStringof the property's[DisplayFormat]attribute, formats numbers and dates. - An enum value shows its member's
[Display]name. - A
boolshows a check or a cross icon, with "Yes" or "No" for screen readers. - An
[EmailAddress]property links to amailto:URL, and a[Url]property links to its URL when it is anhttporhttpsURL. hreflinks the value to any URL.- A collection shows its items separated by commas.
- A
[DataType(DataType.MultilineText)]property keeps its line breaks.
<sa-details columns="3">
<sa-display-field asp-for="LeadTraveller" label="Text" />
<sa-display-field asp-for="Total" label="Number" />
<sa-display-field asp-for="Departure" label="Date" />
<sa-display-field asp-for="CreatedAt" label="Date and time" />
<sa-display-field asp-for="Cabin" label="Enum" />
<sa-display-field asp-for="Email" label="Email address" />
<sa-display-field asp-for="ItineraryPage" label="URL" />
<sa-display-field asp-for="Destination" label="Link" href="#destination-@Model.DestinationId" />
<sa-display-field asp-for="TravelInsurance" label="Boolean (true)" />
<sa-display-field asp-for="VisaRequired" label="Boolean (false)" />
<sa-display-field asp-for="Interests" label="List" />
<sa-display-field asp-for="Infants" label="Zero" />
<sa-display-field asp-for="Notes" label="Multiline text" column-span-full="true" />
</sa-details>Templates and custom content
To render a value with your own markup, such as a badge for a status, set template to the name of a display template, or add a [UIHint] attribute to the property. The template is found like a partial view named DisplayTemplates/{name}, and its model is the value. Templates are only ever used by name: the built-in display templates for a type, such as the checkbox MVC renders for a bool, never apply. A template that cannot be found throws an exception.
Child content replaces the value entirely, and a field with a label and child content needs no asp-for. Set secondary to add muted text after the value.
<sa-details columns="3">
@* [UIHint("BookingStatus")] renders DisplayTemplates/BookingStatus *@
<sa-display-field asp-for="Status" />
@* A named template *@
<sa-display-field asp-for="Reference" template="Reference" />
@* Muted text after the value *@
<sa-display-field asp-for="UpdatedAt" secondary="by @Model.UpdatedBy" />
@* Child content replaces the value *@
<sa-display-field asp-for="Interests">
@foreach (var interest in Model.Interests)
{
<sa-badge variant="BadgeVariant.Secondary">@interest</sa-badge>
}
</sa-display-field>
<sa-display-field asp-for="TravelInsurance">
@(Model.TravelInsurance ? "Included" : "Not included")
</sa-display-field>
<sa-display-field label="Duration">7 nights</sa-display-field>
</sa-details>The status template in this example is a DisplayTemplates/BookingStatus.cshtml view:
@model BookingStatus
@{
var variant = Model switch
{
BookingStatus.Cancelled => BadgeVariant.Destructive,
BookingStatus.Pending => BadgeVariant.Secondary,
_ => BadgeVariant.Default,
};
}
<sa-badge variant="@variant">@Model.ToString()</sa-badge>Among form inputs
Place a <sa-display-field> among the inputs of a form to show a value that cannot be edited. Outside <sa-details> it takes the label style of an input and the height of a control, so a row of inputs and display fields lines up. A <sa-details> in its own Form Section shows information about the record, such as its audit history, below the inputs.
<form>
<sa-form-section title="Booking" description="Who is travelling and where.">
<sa-field-group>
<sa-form-row>
<sa-display-field asp-for="Reference" />
<sa-input asp-for="LeadTraveller" />
</sa-form-row>
<sa-form-row>
<sa-input asp-for="Email" />
<sa-display-field asp-for="Status" />
</sa-form-row>
<sa-textarea asp-for="Notes" rows="3" />
</sa-field-group>
</sa-form-section>
<sa-form-section title="Audit" description="Maintained automatically.">
<sa-details columns="2">
<sa-display-field asp-for="CreatedAt" secondary="by @Model.CreatedBy" />
<sa-display-field asp-for="UpdatedAt" secondary="by @Model.UpdatedBy" />
<sa-display-field asp-for="Version" />
<sa-display-field asp-for="ArchivedAt" />
</sa-details>
</sa-form-section>
</form>Record page
Combine details with Page Header and Form Section to build a page that displays a record.
<sa-page-header class="mb-8">
<sa-page-header-title>@Model.Reference</sa-page-header-title>
<sa-page-header-description>@Model.Destination · @Model.Departure.ToString("d MMM") – @Model.Return.ToString("d MMM yyyy")</sa-page-header-description>
<sa-page-header-actions>
<sa-button variant="ButtonVariant.Outline">Cancel booking</sa-button>
<sa-button>Edit</sa-button>
</sa-page-header-actions>
</sa-page-header>
<sa-form-section title="Booking" description="Who is travelling and where.">
<sa-details columns="2">
<sa-display-field asp-for="Reference" />
<sa-display-field asp-for="Status" />
<sa-display-field asp-for="LeadTraveller" />
<sa-display-field asp-for="Email" />
<sa-display-field asp-for="Destination" href="#destination-@Model.DestinationId" />
<sa-display-field asp-for="Departure" />
<sa-display-field asp-for="Party" />
<sa-display-field asp-for="Total" />
<sa-display-field asp-for="PromoCode" />
</sa-details>
</sa-form-section>
<sa-form-section title="Notes">
<sa-details>
<sa-display-field asp-for="Notes" />
</sa-details>
</sa-form-section>
<sa-form-section title="Audit" description="Maintained automatically.">
<sa-details variant="DetailsVariant.Divided" orientation="FieldOrientation.Horizontal">
<sa-display-field asp-for="CreatedAt" secondary="by @Model.CreatedBy" />
<sa-display-field asp-for="UpdatedAt" secondary="by @Model.UpdatedBy" />
<sa-display-field asp-for="Version" />
<sa-display-field asp-for="ArchivedAt" />
</sa-details>
</sa-form-section>Row details
Use details in the expanded rows of a Table, where the labels are shown at a smaller size.
<sa-table-row-details>
<sa-table>
<sa-table-header>
<sa-table-row>
<sa-table-head class="w-px">
<sa-table-row-detail-toggle all="true"/>
</sa-table-head>
<sa-table-head>Booking #</sa-table-head>
<sa-table-head>Destination</sa-table-head>
<sa-table-head class="text-right">Amount</sa-table-head>
</sa-table-row>
</sa-table-header>
<sa-table-body>
@foreach (var booking in StaticData.Bookings.Take(3))
{
var details = StaticData.DetailsFor(booking.Id);
<sa-table-row>
<sa-table-cell class="w-px">
<sa-table-row-detail-toggle aria-label="Show details for @booking.Id"/>
</sa-table-cell>
<sa-table-cell class="font-medium">@booking.Id</sa-table-cell>
<sa-table-cell>@booking.Destination</sa-table-cell>
<sa-table-cell class="text-right">@booking.Amount.ToString("N2")</sa-table-cell>
</sa-table-row>
<sa-table-row-detail expanded="@(booking.Id == "TRP-4822")">
<sa-details columns="4">
<sa-display-field asp-for="@booking.Status" />
<sa-display-field asp-for="@details.Traveller" label="Lead traveller" />
<sa-display-field asp-for="@details.Email" href="mailto:@details.Email" />
<sa-display-field asp-for="@details.Party" />
<sa-display-field asp-for="@details.Notes" column-span-full="true" />
</sa-details>
</sa-table-row-detail>
}
</sa-table-body>
</sa-table>
</sa-table-row-details>API Reference
<sa-details>
Renders a <div> element around a <dl> element, forwarding any global attributes to the <div>.
Prop
Type
<sa-display-field>
Renders a <div> element holding the label and the value, forwarding any global attributes. Inside <sa-details> the label is a <dt> and the value a <dd>; elsewhere both are <div> elements. Either label or asp-for is required.
Prop
Type