How the field framework is used to handle fields and field data.
Fields and field data are handled by the field framework, where the name of a product is an example of a field. The field framework is designed to support all types of information, from simple text fields to custom fields that cover a special case in the solution. It is divided into field types, field definitions, field templates and in some cases display templates.
Field types
Field type is the lowest level in the field framework and handles how fields are loaded or persisted in the data store. It also creates the correct filter on the field from querying in data service. Field types are global and not bound to a specific part of Litium.
Custom field types can also be created and added to the solution. Read more about that here.
Field definitions
Field definitions are created to define the type of a field. For example, Name is a field of the text type. A field definition contains the instance settings of a field, for example multi-language when it can have values in multiple languages.
Field definitions are specific for the different Areas (formerly known as Modules) of Litium. If you try to save a field that doesn't exist as a field definition in a Litium Area, an exception will be thrown.
This is an example on how to define a new field definition and update the field value:
using System;
using Litium.FieldFramework;
using Litium.Products;
public class FieldDefinitionExample
{
private readonly FieldDefinitionService _fieldDefinitionService;
private readonly FieldTemplateService _fieldTemplateService;
private readonly BaseProductService _baseProductService;
public FieldDefinitionExample(FieldDefinitionService fieldDefinitionService, BaseProductService baseProductService, FieldTemplateService fieldTemplateService)
{
_fieldDefinitionService = fieldDefinitionService;
_baseProductService = baseProductService;
_fieldTemplateService = fieldTemplateService;
}
public void CreateFieldDefinition()
{
var fieldDefinition = new FieldDefinition<ProductArea>("MyField", "text")
{
Localizations =
{
["sv-SE"] = {Name = "Mitt fält", Description = "Mitt fält för att spara information"},
["en-UK"] = {Name = "My field", Description = "My field to save information"},
},
CanBeGridColumn = false,
CanBeGridFilter = true,
};
_fieldDefinitionService.Create(fieldDefinition);
}
public void CreateField()
{
var fieldTemplate = _fieldTemplateService.Get<ProductFieldTemplate>("MyFieldTemplate");
var baseproduct = new BaseProduct("My_baseproduct", fieldTemplate.SystemId);
baseproduct.Fields.AddOrUpdateValue("MyField", "value");
_baseProductService.Create(baseproduct);
var myFieldValue = baseproduct.Fields.GetValue<string>("MyField");
}
public void UpdateField()
{
var baseproduct = _baseProductService.Get("My_baseproduct");
var changableBaseProduct = baseproduct.MakeWritableClone();
changableBaseProduct.Fields.AddOrUpdateValue("MyField", "value2");
_baseProductService.Update(changableBaseProduct);
}
}
Field templates
Field templates are used to decide what an administrator, and in some cases public visitors, will see. They are specified for each entity, for example Category or Product.
In a product field template, fields can be specified for both the base product and a variant. One field can exist in multiple field groups and only specifies if, and where, the field should be visible in the administration view or on the public site.
Values for fields that are not included in any field template can be set through the API:
using System;
using Litium.Products;
public class FieldTemplateExample
{
private readonly FieldTemplateService _fieldTemplateService;
public FieldTemplateExample(FieldTemplateService fieldTemplateService)
{
_fieldTemplateService = fieldTemplateService;
}
public void Main()
{
Guid displayTemplateId;
var fieldTemplate = new ProductFieldTemplate("MyFieldTemplate", displayTemplateId)
{
Localizations =
{
["se-SV"] = {Name = "Min fältmall"},
["en-UK"] = {Name = "My field template"}
},
ProductFieldGroups =
{
new FieldTemplateFieldGroup
{
Localizations =
{
["se-SV"] = {Name = "Min grupp"},
["en-UK"] = {Name = "My group"}
},
Fields =
{
"MyField1",
"MyField2",
"MyField3"
}
}
},
VariantFieldGroups =
{
new FieldTemplateFieldGroup
{
Localizations =
{
["se-SV"] = {Name = "Min grupp"},
["en-UK"] = {Name = "My group"}
},
Fields =
{
"MyField8",
"MyField2",
"MyField5"
}
}
}
};
_fieldTemplateService.Create(fieldTemplate);
}
}
Field Framework tables in Litium 7
In Litium 7, we removed the FieldDefinition, FieldDefinitionFieldData, FieldTemplate, FieldTemplateFieldData tables in each Area (Customer, Media, Product) and created a new set of tables in FieldFramework schema:
This means that all field definitions and field templates in each Area have been moved into one table and separated with an Area column. We can now have have a field _name in the Product area and another _name in the Customer area.
This is how we make a new field definition in CustomerArea:
new FieldDefinition<CustomerArea>("SocialSecurityNumber", SystemFieldTypeConstants.Text)
{
CanBeGridColumn = true,
CanBeGridFilter = true,
MultiCulture = false,
};
And then we could get that field definition like this:
var fieldDefinion = _fieldDefitionService.Get<CustomerArea>("SocialSecurityNumber");
Pointer-field type
Litium 7 introduces a generic pointer type to replace the static ones, like PersonPointer or OrganizationPointer. In the field definion setting screen we can, for example, create a new field definition with type = Pointer. Then we can define the entity type of that pointer in the Entity section.
More info on Pointer-field type could be found here.
Multi-field type
Multi-field is a new concept in Litium 7. In previous versions we could only define basic field types like decimal, int, string, GUID or a JSON value. If we wanted to store an object, the only way was to use a JSON value.
Multi-field allows us to store complex objects in one field defintion. For example, in the sliders block we need to store an array of slides into a block's field. Each slide contains LinkText, ImagePointer and LinkToPage.
More info on the Multi-field type could be found here.
Display templates
A display template is a definition of how the rendering should work, for example the actual template that should be used (WebForm ASPX file of the MVC controller).
The display template for Product also decides if variants should be exposed as separate items with their own URL on the public site, or if they all should be exposed as a product family with one URL.
The display template for Page and Block is a new concept in Litium 7 and is a direct upgrade of PageType in the previous version. For each page type in litium 7, we need to define a controller and a view for it. By selecting the controller name and action in the display template field of the field template, we connect controller, view and field template together. The setting looks like this:
In ArticleController, we can define the logic to build the article page model and return that data to ArticleView, which contains the layout for that page type:
using Litium.Web.Models.Websites;
using System.Web.Mvc;
using Litium.Accelerator.Builders.Article;
namespace Litium.Accelerator.Mvc.Controllers.Article
{
public class ArticleController : ControllerBase
{
private readonly ArticleViewModelBuilder _articleViewModelBuilder;
public ArticleController(ArticleViewModelBuilder articleViewModelBuilder)
{
_articleViewModelBuilder = articleViewModelBuilder;
}
[HttpGet]
public ActionResult Index(PageModel currentPageModel)
{
var model = _articleViewModelBuilder.Build(currentPageModel);
return View(model);
}
}
}
Read-only field
From Litium 7.2, a field can be configured as read only. This means that an editor can't change the field value in back office. Please note that this only affects the user interface. The field can still be updated via the API.