The listing page displays items of the selected object type in a grid-like structure, one item per line, and one field (database column) per column. This page describes how to configure the grid's columns and the elements displayed around it.
Specify the displayed item properties within an override of the ConfigurePage method. Call the AddColumn method on PageConfiguration.ColumnConfigurations and provide the name of the database column to be displayed.
public override Task ConfigurePage()
{
// Adds the specified columns to the grid and sets their caption
PageConfiguration.ColumnConfigurations
// Adds data from the 'UserName', 'FirstName', and 'Email' columns of the 'CMS_User' table
.AddColumn(nameof(UserInfo.UserName), "User name")
.AddColumn(nameof(UserInfo.FirstName), "First name")
.AddColumn(nameof(UserInfo.Email), "Email");
return base.ConfigurePage();
}You can further configure each column by supplying the following optional parameters to the AddColumn method:
Caption – sets a custom caption for the column heading. Defaults to the column name if not set.
Sortable – indicates whether the column can be used to sort the listing.
DefaultSortDirection – a SortTypeEnum value that determines the default order for properties in the column.
Formatter – sets the formatter (opens in a new tab) to use for the column values.
.AddColumn(nameof(UserInfo.UserCreated), formatter: (value, _) => String.Format("{0:MMMM dd, yyyy}", Convert.ToDateTime(value)))Visible – default visibility state of the column. For hidden columns, the data is obtained from the server but hidden.
Searchable – indicates whether column values are searchable via a search box above the listing. If no columns are set as searchable, the search dialog is hidden.
Localizable – persisted values have localization macros resolved.
Tooltip – sets the tooltip for the column.
The listing template supports loading React components inside dedicated columns within the grid via the AddComponentColumn extension method of the PageConfiguration.ColumnConfigurations object.
The method takes identical parameters as AddColumn, with the following additions:
string componentKey – the name of the React component to be displayed. Provide a full name in the {orgName}/{projectName}/component format, as specified when you set up your custom admin JS module. Make sure the component is exported (visible to other modules). For example: @acme/web-admin-custom/MyComponent.
Component naming
When loading the component, the client application suffixes the provided value with TableCellComponent. For the provided example, the client React component must be named MyComponentTableCellComponent.
bool loadedExternally – indicates whether data present in the column is loaded externally (not a property of the *Info object being listed). For example, via a separate ObjectQuery call from a different object.
Func<object, IDataContainer, object> modelRetriever – a function that provides the props for the front-end component to be displayed. The component props data must be wrapped in a dedicated class (for serialization and transfer to the client admin application).
loadedExternally flag is true.IDataContainer). Column values can be accessed using indexer notation.The system instantiates the selected component for each row, with the passed props.
protected override string ObjectType => UserInfo.OBJECT_TYPE;
// ...
public override Task ConfigurePage()
{
PageConfiguration.ColumnConfigurations
// Adds a column displaying a React component with data loaded from UserInfo
.AddComponentColumn(
"assignedRoles",
// Sets the name of the component to render
// When loading the component, the client application automatically suffixes
// the component name with 'TableCellComponent'. For this example, the React
// component must be named 'MyComponentTableCellComponent'.
"@orgName/projectName/MyComponent",
// Sets column caption
"Roles",
modelRetriever: (formattedColumnValue, rowData) =>
{
// 'formattedColumnValue' contains the localized (if localizable) and
// formatted (if a formatter was provided) value of the column
// specified in 'columnName.'
// Empty if the loadedExternally flag is set to 'true'
// 'rowData' contains the entire user record
// from the database (as 'IDataContainer').
// Column values can be accessed using indexer notation.
var userID = (int)rowData[nameof(UserInfo.UserID)];
// Fetches roles assigned to individual users using external logic
// (omitted for brevity).
var userRoles = GetRoles(userID);
// Instantiates a DTO consisting of props for the displayed component
return new ReactComponentToDisplayProps
{
prop1 = userRoles.ToString(),
prop2 = userID
};
},
// Column data will not be fetched as part of the
// ObjectQuery retrieving other UserInfo object data
loadedExternally: true,
sortable: false);
return base.ConfigurePage();
}If the listing offers data export, register a cell value extractor for the component to export the value it displays instead of the stored column value.
You can render arbitrary React components next to the listing page caption via PageConfiguration.SubcaptionComponent.
The following example demonstrates the required configuration:
public override Task ConfigurePage()
{
PageConfiguration.SubcaptionComponent = new MySubcaption
{
ComponentProperties = new MySubcaptionProperties
{
Label = "...",
TooltipText = "..."
},
};
return base.ConfigurePage();
}Where MySubcaption describes the component to render and is defined as follows:
using System.Threading.Tasks;
using Kentico.Xperience.Admin.Base;
// Classes defining subcaption components must inherit from `SubcaptionComponentBase`.
// The two generics describe classes encapsulating the target component's properties on the back-end
// and in the client application. See their definitions below.
public class MySubcaption : SubcaptionComponentBase<MySubcaptionProperties, MySubcaptionClientProperties>
{
// The full name of the React component to render as the subcaption.
// This example targets a custom `MySubcaptionComponent` in the web-admin module.
// You can also use default Xperience components. For example: '@kentico/xperience-admin-components/TextWithLabel'
public override string ComponentName => "@acme/web-admin/MySubcaptionComponent";
// Populates the properties used to instantiate the React component on the client
// Property names must correspond to the properties of the client component
protected override Task ConfigureComponentClientProperties(MySubcaptionClientProperties componentClientProperties)
{
componentClientProperties.Label = ComponentProperties.Label;
componentClientProperties.TooltipText = ComponentProperties.TooltipText;
return base.ConfigureComponentClientProperties(componentClientProperties);
}
}
// Encapsulates the properties of the subcaption component's back-end definition.
// Populated via `PageConfiguration.SubcaptionComponent`. Mapped to 'MySubcaptionClientProperties'
// within the subcaption class ('MySubcaption' in this example).
public class MySubcaptionProperties
{
public string Label { get; set; }
public string TooltipText { get; set; }
}
// Encapsulates properties sent to the client. Used when instantiating the targeted React component.
public class MySubcaptionClientProperties
{
public string Label { get; set; }
public string TooltipText { get; set; }
}Callouts are information messages that can be displayed above the listing grid.
You can add a callout via PageConfiguration.Callouts.
public override Task ConfigurePage()
{
PageConfiguration.Callouts = new List<CalloutConfiguration>()
{
new CalloutConfiguration
{
Headline = "Callout headline",
Content = "Callout text",
Type = CalloutType.QuickTip,
Placement = CalloutPlacement.OnDesk
}
};
return base.ConfigurePage();
}Where CalloutType determines the style of the callout:
And CalloutPlacement determines the callout element width: