Theme

This feature implementations configures DomainModel metadata attributes and extracts component descriptors for ui theme pages and components of an application.

Default

Default Theme feature introduces many components and sets defaults for the domain model. It also configures error pages, layouts, and pages.

To use this theme directly without any update use this;

c => c.Default(
    index: ...,
    routes: [...],
    errorPageOptions: ep => ...,
    sideMenuOptions: sm => ...,
    headerOptions: h => ...,
    debugComponentPaths: ...
)

Or you may prefer to create your custom theme on top of this default theme;

public static class CustomThemeExtensions
{
    public static CustomThemeFeature Custom(this ThemeConfigurator _) =>
        new(
        [
            // All app routes
        ]);
}

public class CustomThemeFeature(IEnumerable<Func<Router, Route>> routes)
    : DefaultThemeFeature(routes.Select(r => r(new())))
{
    public override void Configure(LayerConfigurator configurator)
    {
        // Applies default theme rules
        base.Configure(configurator);

        configurator.ConfigureDomainModelBuilder(builder =>
        {
            // Your custom conventions and page overrides
        });

        configurator.ConfigureComponentExports(c =>
        {
            // Add your component exports using your own `Components` extensions
            // c.AddFromExtensions(typeof(Components));
        });

        configurator.ConfigurePageDescriptors(pages =>
        {
            // Add other pages like `auth/login.vue` etc.
        });
    }
}

Below you can find the rules that comes with this theme. For other user experiences, see UX Feature

GroupRules
TypeTabbedPage and SimplePage is added for any type at component path /page/*
[id] route parameter is mapped to first data property with IdAttribute
PropertyAll public properties get a DataAttribute with a camelized name and titleized label
IdAttribute is added to properties named as Id
Id properties are set to be hidden
string and Guid properties render using String
MethodAll actions with ActionModelAttribute get ActionAttribute and TabNameAttribute
FormPage is added for any method at component path /page/*/*
Content schema is added to any method
Each method is wired as a remote data and remote action
Remote data of locatable types include route.params in their route
For method with parameters Context.Model is set as remote action body by default
ParameterParameters are rendered as Input list under SimpleForm and FormPage inputs
Parameters with ParameterModelAttribute use Input schema
Required and default values are taken from the attribute
string parameters render using InputText
int parameters render using InputNumber
EnumEnum types render inline with EnumInline
Page TitlePageTitle is added for any type at component path /page/*/*page/title
PageTitle is added for any method at component path /page/*/*/*page/title
Actions of type is added to actions section of page title component
Page title actions of locatable types include route.params in their route
Error PageError page includes safe links for routes with ErrorSafeLink
Predefined error messages:
  ↳ 403 Access Denied
  ↳ 404 Page Not Found
  ↳ 500 Unexpected Error
Messages can be customized with errorPageOptions:
LayoutsDefaultLayout includes
  ↳ Side menu with routes marked for SideMenu
  ↳ Header sitemap with enabled routes
Both side menu and header can be customized with sideMenuOptions: and headerOptions:
ModalLayout also included
PagesBuilds pages from routes using domain model and localization
Each route becomes a page if it can be resolved

routes: list is a list of builder functions that takes Router as a parameter and returns Route instance. Three types of route is supported out of the box.

r => r.Index() with { ... },
r => r.Root("/my-parent", "MyParent", "pi pi-user") with { ... },
r => r.Child("/my-parent/my-child", "MyChild", "/my-parent") with { ... },

Page Types

There are three types of page, .Implemented(), .Described(d => ...) and .Generated(g => ...). Each route has a Page property that defines what page to render at that route.

By default pages use .Implemented(), meaning you need to have a .vue page at the given route, e.g. for /my-parent route to work you need to have /pages/my-parent.vue file in the UI project.

r => r.Root("/my-parent", "MyParent", "pi pi-user") with { Page = p => p.Implemented() }

// or

r => r.Root("/my-parent", "MyParent", "pi pi-user")

.Described(d => ...) is appropriate when you decide to fully describe the page manually from your theme feature. Add an extension method to Page.Describer for your custom page and use it in routes.

r => r.Root("/my-parent", "MyParent", "pi pi-user") with { Page = p => p.Described(d => d.MyParent()) }

.Generated(g => ...) is appropriate when you have necessary conventions to generate a page descriptor out of a domain model.

r => r.Root("/my-parent", "MyParent", "pi pi-user") with { Page = p => p.Generated(g => g.From<MyParent>()) }