Templates in DataForm component
12 Jan 202424 minutes to read
In DataForm component we can customize the specific editor field or the entire form components using template feature.
Customization of specific field editor
We can customize the particular field editor with required UI customization using the Template RenderFragment
inside FormItem
tag.
@using Syncfusion.Blazor.DataForm
@using System.ComponentModel.DataAnnotations
@using Syncfusion.Blazor.Inputs
@using Syncfusion.Blazor.Calendars
<SfDataForm ID="MyForm"
Model="@CreditCardModel"
Width="50%">
<FormValidator>
<DataAnnotationsValidator></DataAnnotationsValidator>
</FormValidator>
<FormItems>
<FormItem Field="@nameof(CreditCardModel.Name)" Placeholder="e.g. Andrew Fuller" LabelText="Name on card" ></FormItem>
<FormItem Field="@nameof(CreditCardModel.CardNumber)" LabelText="Card Number" >
</FormItem>
<FormItem Field="@nameof(CreditCardModel.CVV)">
<Template>
<label class="e-form-label">CVV*:</label>
<SfMaskedTextBox Mask="000" @bind-Value="CreditCardModel.CVV" ></SfMaskedTextBox>
</Template>
</FormItem>
<FormItem Field="@nameof(CreditCardModel.ExpiryDate)">
<Template>
<label class="e-form-label">Expiry Date*:</label>
<SfDatePicker TValue="DateTime?" Format="MM/yy" EnableMask="true"></SfDatePicker>
</Template>
</FormItem>
</FormItems>
</SfDataForm>
@code {
public char PromptCharacter { get; set; } = ' ';
public class CreditCard
{
[Required(ErrorMessage = "Please enter the name on card")]
public string Name { get; set; }
[Required(ErrorMessage = "Please enter the card number")]
[CreditCard]
public string CardNumber { get; set; }
[Required(ErrorMessage = "Please enter cvv number")]
public string CVV { get; set; }
[Required(ErrorMessage = "Please select/enter expiry date")]
public DateTime? ExpiryDate { get; set; }
}
private CreditCard CreditCardModel = new CreditCard();
}
We can also utilize the above Template
combination with FormAutoGenerateItems which will generate the items except the specified Formitem
.
Customization of entire form
DataForm
have the ability to customize the entire structure of the form, incorporating necessary components within it, and we can also personalize the messages displayed for validation errors.
@using System.ComponentModel;
@using System.ComponentModel.DataAnnotations
@using Syncfusion.Blazor.DataForm
@using Syncfusion.Blazor.Buttons
@using Syncfusion.Blazor.Inputs
@using Syncfusion.Blazor.Calendars
@using Syncfusion.Blazor.DropDowns
@using Syncfusion.Blazor.Navigations
<div class="form-section">
<SfDataForm ID="MyForm"
Model="ProductDetailsModel"
Width="50%"
ButtonsAlignment="FormButtonsAlignment.Center">
<FormValidator>
<DataAnnotationsValidator></DataAnnotationsValidator>
</FormValidator>
<FormTemplate>
<SfAccordion ExpandMode="ExpandMode.Single">
<AccordionItems>
<AccordionItem Expanded="true">
<HeaderTemplate>Product Info</HeaderTemplate>
<ContentTemplate>
<div class="product-details">
<div class="form-group">
<label class="e-form-label">Category</label>
<SfTextBox @bind-Value="ProductDetailsModel.Category" Readonly="true" />
</div>
<div class="form-group">
<label class="e-form-label">Brand</label>
<SfDropDownList TValue="string" TItem="string" DataSource="BrandData" @bind-Value="ProductDetailsModel.Brand">
</SfDropDownList>
<ValidationMessage For="()=>(ProductDetailsModel.Brand)"></ValidationMessage>
</div>
<div class="form-group">
<label class="e-form-label">Color</label>
<SfDropDownList TValue="string" TItem="string" DataSource="Colors" @bind-Value="ProductDetailsModel.Color"></SfDropDownList>
<ValidationMessage For="()=>(ProductDetailsModel.Color)"></ValidationMessage>
</div>
<div class="form-group">
<label class="e-form-label">Size</label>
<SfDropDownList TValue="string" TItem="string" DataSource="SizeData" @bind-Value="ProductDetailsModel.Size"></SfDropDownList>
<ValidationMessage For="()=>(ProductDetailsModel.Size)"></ValidationMessage>
</div>
</div>
</ContentTemplate>
</AccordionItem>
<AccordionItem Expanded="false">
<HeaderTemplate>Payment Details</HeaderTemplate>
<ContentTemplate>
<div class="payment-info">
<div class="form-group">
<label class="e-form-label">Contact Number</label>
<SfMaskedTextBox Mask="+(00) 0000000000" Placeholder="eg. +12 1234567890" @bind-Value="ProductDetailsModel.ContactNumber" />
<ValidationMessage For="()=>(ProductDetailsModel.ContactNumber)"></ValidationMessage>
</div>
<div class="form-group">
<label class="e-form-label">Shipping Address</label>
<SfTextBox Multiline="true" @bind-Value="ProductDetailsModel.ShippingAddress" />
<ValidationMessage For="()=>(ProductDetailsModel.ShippingAddress)"></ValidationMessage>
</div>
<div class="form-group">
<label class="e-form-label">Delivery Instructions (Optional)</label>
<SfTextBox Multiline="true" @bind-Value="ProductDetailsModel.DeliveryInstructions" Placeholder="Landmark , alternate contact number etc.. " />
</div>
</div>
</ContentTemplate>
</AccordionItem>
</AccordionItems>
</SfAccordion>
</FormTemplate>
<FormButtons>
<SfButton>Buy now</SfButton>
</FormButtons>
</SfDataForm>
</div>
@code {
public string[] BrandData = new string[] { "Adidas", "Puma", "Reebok", "Nike", "Skechers", "Vans" };
public string[] Colors = new string[] { "Black", "Grey", "White", "Red", "Beige", "Pink", "Off-White" };
public string[] SizeData = new string[] { "6UK", "7UK", "8UK", "9UK", "10UK", "11UK" };
private ProductDetails ProductDetailsModel = new ProductDetails()
{
Category = "Shoes - Men",
Color = "Black",
Size = "6UK"
};
}
public class ProductDetails
{
public string Category { get; set; }
[Required(ErrorMessage = "Please choose the brand.")]
public string Brand { get; set; }
[Required(ErrorMessage = "Please enter the color.")]
public string Color { get; set; }
[Required(ErrorMessage = "Please enter the size.")]
public string Size { get; set; }
[Required(ErrorMessage = "Please enter the shipping address.")]
public string ShippingAddress { get; set; }
public string BillingAddress { get; set; }
public string DeliveryInstructions { get; set; }
[Required(ErrorMessage = "Please enter your contact number.")]
public string ContactNumber { get; set; }
}
<style>
.control-wrapper {
max-width: 400px;
margin: 0 auto;
padding: 0px 0px 0px;
}
.control-header {
text-align: center;
}
.form-group {
margin-bottom: 1em;
}
.form-section {
margin-top: 20x;
}
.sf-icon-shopping-cart_01-:before {
content: "\e710";
}
.sf-icon-check:before {
content: "\e715";
}
@@font-face {
font-family: 'Default';
src: url(data:application/x-font-ttf;charset=utf-8;base64,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) format('truetype');
font-weight: normal;
font-style: normal;
}
[class^="sf-icon-"], [class*=" sf-icon-"] {
font-family: 'Default' !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: inherit;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</style>
We can also integrate the FormTemplate
renderer along with FormItem
as showcased in the below example.
@using Syncfusion.Blazor.DataForm
@using System.ComponentModel.DataAnnotations
<SfDataForm Width="50%"
Model="@RegistrationDetailsModel">
<FormValidator>
<DataAnnotationsValidator></DataAnnotationsValidator>
</FormValidator>
<FormItems>
<FormItem Field="@nameof(RegistrationDetailsModel.Name)"></FormItem>
</FormItems>
<FormTemplate>
@* Insert your template layout code here to incorporate additional editor components corresponding to their respective fields *@
</FormTemplate>
</SfDataForm>
@code {
public class RegistrationDetails
{
[Required(ErrorMessage = "Please enter your name")]
public string Name { get; set; }
[Required(ErrorMessage = "Please enter your email address")]
[EmailAddress(ErrorMessage = "Please enter valid email address")]
public string Email { get; set; }
}
private RegistrationDetails RegistrationDetailsModel = new RegistrationDetails();
}
Tooltip validation message with template
When using the Template
renderer, we can also customize the validation message with the help of Tooltip
component by setting ID
field to the custom editor component similar to the form item’s ID
property.
@using Syncfusion.Blazor.DataForm
@using System.ComponentModel.DataAnnotations
@using Syncfusion.Blazor.Inputs
@using Syncfusion.Blazor.Calendars
<SfDataForm ID="MyForm"
Model="@CreditCardModel"
ValidationDisplayMode="FormValidationDisplay.Tooltip">
<FormValidator>
<DataAnnotationsValidator></DataAnnotationsValidator>
</FormValidator>
<FormItems>
<FormItem Field="@nameof(CreditCardModel.Name)" Placeholder="e.g. Andrew Fuller" LabelText="Name on card"></FormItem>
<FormItem Field="@nameof(CreditCardModel.CardNumber)" LabelText="Card Number">
</FormItem>
<FormItem Field="@nameof(CreditCardModel.CVV)" ID="CVV">
<Template>
<label class="e-form-label">CVV*:</label>
<SfMaskedTextBox Mask="000" @bind-Value="CreditCardModel.CVV" ID="CVV"></SfMaskedTextBox>
</Template>
</FormItem>
<FormItem Field="@nameof(CreditCardModel.ExpiryDate)" ID="ExpiryDate">
<Template>
<label class="e-form-label">Expiry Date*:</label>
<SfDatePicker TValue="DateTime?" Format="MM/yy" EnableMask="true" ID="ExpiryDate"></SfDatePicker>
</Template>
</FormItem>
</FormItems>
</SfDataForm>
@code {
public char PromptCharacter { get; set; } = ' ';
private CreditCard CreditCardModel = new CreditCard();
}
public class CreditCard
{
[Required(ErrorMessage = "Please enter the name on card")]
public string Name { get; set; }
[Required(ErrorMessage = "Please enter the card number")]
[CreditCard]
public string CardNumber { get; set; }
[Required(ErrorMessage = "Please enter cvv number")]
public string CVV { get; set; }
[Required(ErrorMessage = "Please select/enter expiry date")]
public DateTime? ExpiryDate { get; set; }
}
Validation summary
The ValidationSummary tag can be utilized to present a summary of validation messages, and it should be positioned within the FormValidator
tag to function correctly.The below example demonstrates the usage of it.
@using Syncfusion.Blazor.DataForm
@using System.ComponentModel.DataAnnotations
@using Syncfusion.Blazor.Inputs
@using Syncfusion.Blazor.Calendars
<SfDataForm ID="MyForm"
Model="@CreditCardModel"
ValidationDisplayMode="FormValidationDisplay.Tooltip">
<FormValidator>
<DataAnnotationsValidator></DataAnnotationsValidator>
<ValidationSummary></ValidationSummary>
</FormValidator>
<FormItems>
<FormItem Field="@nameof(CreditCardModel.Name)" Placeholder="e.g. Andrew Fuller" LabelText="Name on card"></FormItem>
<FormItem Field="@nameof(CreditCardModel.CardNumber)" LabelText="Card Number">
</FormItem>
<FormItem Field="@nameof(CreditCardModel.CVV)" ID="CVV">
<Template>
<label class="e-form-label">CVV*:</label>
<SfMaskedTextBox Mask="000" @bind-Value="CreditCardModel.CVV" ID="CVV"></SfMaskedTextBox>
</Template>
</FormItem>
<FormItem Field="@nameof(CreditCardModel.ExpiryDate)" ID="ExpiryDate">
<Template>
<label class="e-form-label">Expiry Date*:</label>
<SfDatePicker TValue="DateTime?" Format="MM/yy" EnableMask="true" ID="ExpiryDate"></SfDatePicker>
</Template>
</FormItem>
</FormItems>
</SfDataForm>
@code {
public char PromptCharacter { get; set; } = ' ';
private CreditCard CreditCardModel = new CreditCard();
}
public class CreditCard
{
[Required(ErrorMessage = "Please enter the name on card")]
public string Name { get; set; }
[Required(ErrorMessage = "Please enter the card number")]
[CreditCard]
public string CardNumber { get; set; }
[Required(ErrorMessage = "Please enter cvv number")]
public string CVV { get; set; }
[Required(ErrorMessage = "Please select/enter expiry date")]
public DateTime? ExpiryDate { get; set; }
}