Control customization

Controls can be customized both on the server side with a class derived from ControlBase and on the client side with a Vue.js component.
It is not necessary to apply both customizations simultaneously; in fact, in most cases, customizing the class is more than sufficient to achieve the desired behavior.
 
Custom Control Class
To have a custom class, create a new C# class in the project.
Usually, the file is placed in Areas/DataWeb/Infrastructure/Data/Form/Controls, creating a folder with the name of the item (for example, Product).
The class name is prefixed with the item name plus "_" plus the control name (for example: Product_Code).
 
Class path
 
For better code organization, the class can use the namespace [ProjectNamespace].DataWeb.Data.Controls.
The class can directly derive from ControlBase or more conveniently from a default control like TextBox.
This way, the amount of code to write will be further reduced, leaving a significant part of the customization to the default control.
Here's an example of a custom TextBox class to validate the uniqueness of a product code.
 
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using DataWeb.Structure;
using DataWeb.Identity;
using DataWeb.Data;
using DataWeb.Data.Controls;
using DataWeb.Validation;
using DataWeb.WebApp.Infrastructure;

namespace MyApp.DataWeb.Data.Controls
{
    public class Product_Code :  TextBox
    {
        private readonly ProductStore productRepository;

        public Product_Code(Form form, IServiceProvider serviceProvider) : base(form, serviceProvider)
        {
            productRepository = serviceProvider.GetService<ProductStore>();
        }

        public override async Task<List<ValidationError>>ValidateAsync(object value, List<Form.ProvidedValue> providedValues, Dictionary<string, object> sectionData, IUser user, string itemId = null, NavigationContext navigationContext = null)
        {
            var errors = await base.ValidateAsync(value, providedValues, sectionData, user, itemId, navigationContext);

            var products = await productRepository.GetProductsAsync(new ProductStore.Filter { PublishMode = PublishMode.Management }, "en-US");
            if (products.Any(x => x.Code.Equals(Convert.ToString(value), StringComparison.OrdinalIgnoreCase) && x.IdMaster != itemId))
            {
                errors.Add(new ValidationError { Name = "Code", Message = "Code already exists" });
            }

            return errors;
        }
    }
}
 
The final step requires updating the form in DataWeb to indicate to the control to use this custom class.
The value entered should be the namespace plus "." plus the class name. In this case: MyApp.DataWeb.Data.Controls.Product_Code.
 
Form custom class
 
Custom Control Component
To customize the ergonomics of a control, you can create a Vue.js component that will be attached to the control during the form rendering phase. In this case, the component should be placed in Areas/DataWeb/Scripts/Components/Controls.
The name of the component is the item name plus "_" plus the control name.
Finally, the component can be associated with the control in the Control component name field, where you should enter the name of the reference tag (thus not the filename, but the tag associated during Vue.js configuration). Additionally, parameters can be added to use the same component with different configurations.
 
Form custom component