Module: Page Builder
5 of 15 Pages
Define the template's properties
Now that we have view models to determine the product template’s data, let’s add properties, so that editors can configure its appearance.
The properties will utilize dropdowns fed by the dropdown provider we created earlier in this series, so start by defining enumerations for different color scheme and corner style options.
Decorate options with the Description
attribute to provide user-friendly names.
In the ~/Features/Shared/OptionProviders/ColorScheme directory:
C#ColorSchemeOption.csusing System.ComponentModel; namespace TrainingGuides.Web.Features.Shared.OptionProviders.ColorScheme; public enum ColorSchemeOption { [Description("Light background, dark text")] Light1 = 1, [Description("Light background, dark text 2")] Light2 = 2, [Description("Light background, dark text 3")] Light3 = 3, [Description("Transparent background, dark text")] TransparentDark = 4, [Description("Transparent background, medium text")] TransparentMedium = 5, [Description("Transparent background, light text")] TransparentLight = 6, [Description("Dark background, light text")] Dark1 = 7, [Description("Dark background, light text 2")] Dark2 = 8 }
In the ~/Features/Shared/OptionProviders/CornerStyle directory:
C#CornerStyleOption.csusing System.ComponentModel; namespace TrainingGuides.Web.Features.Shared.OptionProviders.CornerStyle; public enum CornerStyleOption { [Description("Sharp corners")] Sharp = 0, [Description("Round corners")] Round = 1, [Description("Very round corners")] VeryRound = 2, }
Next, create a properties class for the ProductPage content type that utilizes these dropdowns in the ~/Features/Products folder.
using Kentico.PageBuilder.Web.Mvc.PageTemplates;
using Kentico.Xperience.Admin.Base.FormAnnotations;
using TrainingGuides.Web.Features.Shared.OptionProviders;
using TrainingGuides.Web.Features.Shared.OptionProviders.CornerStyle;
using TrainingGuides.Web.Features.Shared.OptionProviders.ColorScheme;
namespace TrainingGuides.Web.Features.Products;
public class ProductPagePageTemplateProperties : IPageTemplateProperties
{
[DropDownComponent(
Label = "Color scheme",
ExplanationText = "Select the color scheme of the template.",
DataProviderType = typeof(DropdownEnumOptionProvider<ColorSchemeOption>),
Order = 20)]
public string ColorScheme { get; set; } = nameof(ColorSchemeOption.TransparentDark);
[DropDownComponent(
Label = "Corner style",
ExplanationText = "Select the corner type of the template.",
DataProviderType = typeof(DropdownEnumOptionProvider<CornerStyleOption>),
Order = 30)]
public string CornerStyle { get; set; } = nameof(CornerStyleOption.Round);
}
Set up the template
With the view models and service in place, we can create the page template, register it, and serve it from a controller.
Find more details here
This section briefly goes over processes covered in Build a page template step of our Kickstart series. Please refer to it if you’d like more detailed steps and information in the context of a different example.
Note these sections in particular:
Define the view
With the view model and properties in place, you can create a view under ~/Features/Products.
Use the GetTemplateModel
method to retrieve structured data and display it in a view. We’ll expand on this in the future. For now, let’s keep it simple.
@using TrainingGuides.Web.Features.Products.Models
@using TrainingGuides.Web.Features.Products
@model TemplateViewModel<ProductPagePageTemplateProperties>
@{
var templateModel = Model.GetTemplateModel<ProductPageViewModel>();
}
<div>
<div>
<h3>@templateModel.NameHtml</h3>
<p>@templateModel.ShortDescriptionHtml</p>
</div>
<div>
<img src="@templateModel.Media.FirstOrDefault()?.FilePath" alt="@templateModel.Media.FirstOrDefault()?.Description"/>
</div>
</div>
Register the template
Create a new file called ProductPagePageTemplate.cs in the ~/Features/Products folder, and use it to house the registration attribute for the page template.
using Kentico.PageBuilder.Web.Mvc.PageTemplates;
using TrainingGuides;
using TrainingGuides.Web.Features.Products;
[assembly: RegisterPageTemplate(
identifier: ProductPagePageTemplate.IDENTIFIER,
name: "Product page template",
propertiesType: typeof(ProductPagePageTemplateProperties),
customViewName: "~/Features/Products/ProductPagePageTemplate.cshtml",
ContentTypeNames = [ProductPage.CONTENT_TYPE_NAME],
IconClass = "xp-box")]
namespace TrainingGuides.Web.Features.Products;
public static class ProductPagePageTemplate
{
public const string IDENTIFIER = "TrainingGuides.ProductPageTemplate";
}
Create the controller
- In the ~/Features/Products folder, add a file called ProductPageController.
- Use an
IContentItemRetriever<ProductPage>
to get the product data from Xperience. - Use an instance of the
IProductPageService
we defined earlier to convert theProductPage
to aProductPageViewModel
. - Add a new
ProductFeatureViewModel
containing the product’s price, so that it appears in the table.
using Kentico.Content.Web.Mvc;
using Kentico.Content.Web.Mvc.Routing;
using Kentico.PageBuilder.Web.Mvc.PageTemplates;
using Microsoft.AspNetCore.Mvc;
using TrainingGuides;
using TrainingGuides.Web.Features.Products.Models;
using TrainingGuides.Web.Features.Products.Services;
using TrainingGuides.Web.Features.Shared.Services;
[assembly: RegisterWebPageRoute(
contentTypeName: ProductPage.CONTENT_TYPE_NAME,
controllerType: typeof(TrainingGuides.Web.Features.Products.ProductPageController))]
namespace TrainingGuides.Web.Features.Products;
public class ProductPageController : Controller
{
private readonly IWebPageDataContextRetriever webPageDataContextRetriever;
private readonly IContentItemRetrieverService<ProductPage> contentItemRetriever;
private readonly IProductPageService productPageService;
public ProductPageController(
IWebPageDataContextRetriever webPageDataContextRetriever,
IContentItemRetrieverService<ProductPage> contentItemRetriever,
IProductPageService productPageService)
{
this.webPageDataContextRetriever = webPageDataContextRetriever;
this.contentItemRetriever = contentItemRetriever;
this.productPageService = productPageService;
}
public async Task<IActionResult> Index()
{
var context = webPageDataContextRetriever.Retrieve();
var productPage = await contentItemRetriever.RetrieveWebPageById
(context.WebPage.WebPageItemID,
ProductPage.CONTENT_TYPE_NAME,
3);
var model = await productPageService.GetProductPageViewModel(productPage);
model.Features.Add(
new ProductFeatureViewModel
{
Key = "price-from-product-content-item",
Name = "Price",
LabelHtml = new("Price"),
Price = model.Price,
ValueHtml = new(string.Empty),
FeatureIncluded = false,
ValueType = ProductFeatureValueType.Number,
ShowInComparator = true,
});
return new TemplateResult(model);
}
}
Check your progress
We’ve been focused on code for a while, so let’s double-check that everything is working on the site.
- Log into the Xperience admin and open the Training guides pages channel.
- Choose one of the Product page pages under the Products page in the tree, and edit the page on the Page Builder tab.
- Click the page icon in the bottom left corner of the Page Builder frame to configure the Page Builder properties.
- Choose the Product page template, and see how the data from the product page is now displayed according to your templates.
If you’re not seeing any output, make sure the product page type is included in the UsePageBuilder
call during the application’s startup sequence, try putting breakpoints in the controller and view. If one or both of them is not being hit, it could indicate an issue in one of the registration attributes for the controller or page template.