View Components
Grid
The "Grid"
view component can be used to display tabular data with paging, sorting and filtering. It uses a data provider as the source of data, which usually come from a database.
The grid must contain one or more columns, for example:
@await Component.InvokeAsync( "Grid", GridOptions.Create( Model.DataProvider, builder => builder
.AddColumn( "name", _( "Name" ), u => u.Name )
.AddColumn( "email", _( "Email" ), u => u.Email )
) )
Each column contains a key, which can be used for sorting, a header, and a function returning the cell’s value. The value can be a string or an IHtmlContent
containing HTML elements.
Details column
The AddDetailsColumn()
method of the GridOptionsBuilder
creates a column which contains a link to a details action, for example:
@await Component.InvokeAsync( "Grid", GridOptions.Create( Model.DataProvider, builder => builder
.AddDetailsColumn( "name", _( "Name" ), u => u.Name, u => u.Id )
) )
The fourth parameter is a function returning the ID of the object, passed to the details action route (and the additional actions, if defined). It can also return an object containing route values.
The optional fifth parameter can specify the name of the details action; if not specified, it defaults to "Details"
. The optional sixth parameter can specify the name of the controller containing the details action (and the additional actions, if defined); if not specified, it defaults to the current controller.
The final parameter of the AddDetailsColumn()
method can be used to create any number of additional action links, which are displayed below the details link, for example:
@await Component.InvokeAsync( "Grid", GridOptions.Create( Model.DataProvider, builder => builder
.AddDetailsColumn( "name", _( "Name" ), u => u.Name, u => u.Id, actions => actions
.AddAction( new ActionItem { Action = "Edit", Label = _( "Edit" ), Icon = "pencil" } )
.AddAction( new ActionItem { Action = "Delete", Label = _( "Delete" ), Icon = "trash", Class = "is-delete" } )
)
) )
The ActionItem
object should contain the name of the action, its label and an optional icon. If the Post
property is set to true
, the action is performed using a POST request, which makes it possible to execute actions which change the object’s state without the risk of a CSRF attack (see Security for more details). Finally, an additional CSS class can be specified.
A function which takes a row model and returns an ActionItem
can also be passed to the AddAction()
method. The function can return null
to prevent an action from being created. For example:
@await Component.InvokeAsync( "Grid", GridOptions.Create( Model.DataProvider, builder => builder
.AddDetailsColumn( "name", _( "Name" ), u => u.Name, u => u.Id, actions => actions
.AddAction( new ActionItem { Action = "Edit", Label = _( "Edit" ), Icon = "pencil" } )
.AddAction( user => {
if ( user.CanDelete )
return new ActionItem { Action = "Delete", Label = _( "Delete" ), Icon = "trash", Class = "is-delete" };
return null;
} )
)
) )
Actions column
The AddActionsColumn()
method of the GridOptionsBuilder
creates a column which contains buttons for executing actions. This allows to create a more compact table than when using AddDetailsColumn()
. For example:
@await Component.InvokeAsync( "Grid", GridOptions.Create( Model.DataProvider, builder => builder
.AddActionsColumn( u => u.Id, actions => actions
.AddAction( new ActionItem { Action = "Edit", Label = _( "Edit" ), Icon = "pencil" } )
.AddAction( new ActionItem { Action = "Delete", Label = _( "Delete" ), Icon = "trash", Class = "is-delete" } )
)
) )
In this case, the key, header and the function returning the cell’s value are not specified. The first parameter is a function returning the ID of the object, passed to the action routes. It can also return an object containing route values.
The optional second parameter can specify the name of the controller containing the actions; if not specified, it defaults to the current controller.
The last parameter is used to create action items. The icons are mandatory and the labels are displayed as tooltips. The available CSS classes are is-primary
, is-create
and is-delete
.
Styling the table
The wrapper element for the grid view contains a CSS class created from the data providers model type, converted to lowercase, for example is-model-user
for the User
type.
Each column of the grid contains a CSS class created from the column’s key, for example is-attr-name
and is-attr-email
.
The application can use these classes to specify the width of each column in the grid, for example:
.grid-view.is-model-user {
.is-attr-name {
@include column-width-dynamic( lg, 1 );
}
.is-attr-email {
@include column-width( md );
}
}
The column widths can be xs
, sm
, base
, md
, lg
, xl
or 2xl
. One or more columns should have dynamic width; in that case they extend to fill the available space, and the first parameter specifies the minimum width.
Detail
The "Detail"
view component can be used to display details of a single item as a table, for example:
@await Component.InvokeAsync( "Detail", DetailOptions.Create( Model, builder => builder
.AddRow( _( "Name" ), u => u.Name )
.AddRow( _( "Email" ), u => u.Email )
) )
Each row contains a header and a function returning the cell’s value. The value can be a string or an IHtmlContent
containing HTML elements.
An optional key can also be passed as the first parameter of the AddRow()
method. It is used to create a CSS class for the row, which can be used for styling the table. For example:
.detail-view.is-model-event {
.is-attr-message {
white-space: pre-wrap;
}
}
The AddCondition()
method of the DetailOptionsBuilder
can be used to create rows which are conditionally visible. The first parameter is a function returning true
if the rows should be visible and false
otherwise, and the second parameter is a function which receives a child DetailOptionsBuilder
which can be used to define conditionally visible rows, for example:
@await Component.InvokeAsync( "Detail", DetailOptions.Create( Model, builder => builder
.AddRow( _( "Name" ), u => u.Name )
.AddCondition( u => u.IsAdministrator, builder => builder
.AddRow( _( "Email" ), u => u.Email )
)
) )
Conditions can be nested by calling the AddCondition()
method of the child DetailOptionsBuilder
.
Application header
The "ApplicationHeader"
view component can be used to display a header bar with the application’s logo and/or name, an optional side menu and an optional top menu, for example:
@await Component.InvokeAsync( "ApplicationHeader", new ApplicationHeaderOptions
{
LogoUrl = Url.Content( "~/images/logo.svg" ),
Title = "My App",
SideItems = new MenuItem[]
{
new MenuItem { Label = _( "Home Page" ), Icon = "house", Url = Url.Action( "Index", "Home" ) },
// ...
},
TopItems = new MenuItem[]
{
new MenuItem { Label = _( "Log in" ), Icon = "log-in", Url = Url.Action( "Login", "Account" ) },
// ...
},
} )
The top menu is displayed in the top right corner as icons with optional drop-down menus.
The side menu is displayed on the left side of the page. It can contain items and groups of items. In mobile view, the side menu is collapsed, and it can be expanded using a button at the top of the page.
Each menu item should contain a label and an icon. Action items should contain an URL, and drop-down menus and groups of items should contain an Items
property with child menu items, for example:
SideItems = new MenuItem[]
{
new MenuItem { Label = _( "Administration Panel" ), Icon = "cog", Items = new MenuItem[]
{
new MenuItem { Label = _( "Users" ), Icon = "users", Url = Url.Action( "Index", "Users" ) },
new MenuItem { Label = _( "Event Log" ), Icon = "book", Url = Url.Action( "Index", "Events" ) },
} },
},
If the Post
property is set to true
, the action is performed using a POST request, which makes it possible to execute actions which change the object’s state without the risk of a CSRF attack (see Security for more details). Finally, an additional class can be specified.
If the Visible
property is set to false
, the action is hidden. If all items in a menu or group are hidden, the entire menu or group is hidden as well.
The Class
property can be used to specify an additional CSS class for the item.
The application header also contains a button which makes it possible to change the font size and store it in a cookie.