- Inline or dialog template editing
- Using template context
- Render tab control inside the dialog template
Contact Support
Template editing in ASP.NET MVC Grid component
30 Dec 202424 minutes to read
The Syncfusion ASP.NET MVC Grid component supports template editing, providing a powerful and flexible way to customize the appearance and behavior of cells during editing. This feature allows you to use ASP.NET MVC templates to define the structure and content of the cells within the grid.
Inline or dialog template editing
The Syncfusion Grid provides support for inline and dialog template editing, allowing you to customize the editing using Forms
. These forms can be utilized to add and update grid records.
To enable this feature, you need to set the EditSettings.Mode property of the Grid to either Normal or Dialog and define the grid editors using EditSetting.Template.
Using Forms
Forms is a approach to create and manipulate the form controls. You can use form to add and update grid records. To use forms for editing operation, you can take leverage of the template support of dialog or inline edit mode. Setting the EditSettings.Mode as Normal/Dialog and use EditSetting.Template property to specify a SCRIPT element ID or an HTML string that holds the template.
In some cases, you want to add new field editors in the dialog which are not present in the column model. In that situation the dialog template will help us to customize the default edit dialog.
In the following sample, grid enabled with dialog template editing.
@Html.EJS().Grid("grid").DataSource((IEnumerable<object>)ViewBag.DataSource).ActionComplete("actionComplete").Height("348px").Columns(col =>
{
col.Field("OrderID").HeaderText("Order ID").IsPrimaryKey(true).Width("120").ValidationRules(new { required = "true" }).TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Add();
col.Field("CustomerID").HeaderText("Customer Name").Width("150").Add();
col.Field("ShipCountry").HeaderText("Ship Country").Width("150").Add();
}).AllowPaging().EditSettings(edit => { edit.AllowAdding(true).AllowEditing(true).AllowDeleting(true).Mode(Syncfusion.EJ2.Grids.EditMode.Dialog).Template("#dialogtemplate"); }).Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" }).Render()
<script>
function actionComplete(args) {
let spinner = ej.popups.createSpinner({ target: args.dialog.element });
ej.popups.showSpinner(args.dialog.element);
if (args.requestType === 'beginEdit') {
var ajax = new ej.base.Ajax({
url: "/Home/EditPatial", //render the partial view
type: "POST",
contentType: "application/json",
data: JSON.stringify({ value: args.rowData })
});
ajax.send().then(function (data) {
$("#dialogTemp").html(data); //Render the edit form with selected record
args.form.elements.namedItem('CustomerID').focus();
ej.popups.hideSpinner(args.dialog.element);
}).catch(function (xhr) {
console.log(xhr);
ej.popups.hideSpinner(args.dialog.element);
});
}
if (args.requestType === 'add') {
var ajax = new ej.base.Ajax({
url: "/Home/AddPatial", //render the partial view
type: "POST",
contentType: "application/json",
});
ajax.send().then(function (data) {
$("#dialogTemp").html(data); //Render the edit form with selected record
args.form.elements.namedItem('OrderID').focus();
ej.popups.hideSpinner(args.dialog.element);
}).catch(function (xhr) {
console.log(xhr);
ej.popups.hideSpinner(args.dialog.element);
});
}
}
</script>
<script id='dialogtemplate' type="text/x-template">
<div id="dialogTemp"></div>
</script>
<style>
.form-group.col-md-6 {
width: 250px;
}
#ShipAddress {
resize: vertical;
}
textarea {
max-width: 100%;
}
</style>
@using Syncfusion.EJ2;
<div>
<div class="form-row">
<div class="form-group col-md-6">
<div class="e-float-input e-control-wrapper">
<input asp-for="OrderID" name="OrderID" type='text' />
<span class="e-float-line"></span>
<label asp-for="OrderID" class="e-float-text e-label-top">Order ID</label>
</div>
</div>
<div class="form-group col-md-6">
<div class="e-float-input e-control-wrapper">
<input asp-for="CustomerID" name="CustomerID" />
<span class="e-float-line"></span>
<label asp-for="CustomerID" class="e-float-text e-label-top">Customer Name</label>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
@Html.EJS().NumericTextBox("Freight").Format("C2").Placeholder("Freight").FloatLabelType(Syncfusion.EJ2.Inputs.FloatLabelType.Always).Render()
</div>
<div class="form-group col-md-6">
@Html.EJS().DatePicker("OrderDate").Placeholder("Order Date").FloatLabelType(Syncfusion.EJ2.Inputs.FloatLabelType.Always).Render()
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
@Html.EJS().DropDownList("ShipCountry").DataSource(ViewBag.dataSource).Placeholder("Ship Country").Fields(new Syncfusion.EJ2.DropDowns.DropDownListFieldSettings { Text = "ShipCountry", Value = "ShipCountry" }).FloatLabelType(Syncfusion.EJ2.Inputs.FloatLabelType.Always).Render()
</div>
<div class="form-group col-md-6">
@Html.EJS().DropDownList("ShipCity").DataSource(ViewBag.dataSource).Placeholder("Ship City").Fields(new Syncfusion.EJ2.DropDowns.DropDownListFieldSettings { Text = "ShipCity", Value = "ShipCity" }).FloatLabelType(Syncfusion.EJ2.Inputs.FloatLabelType.Always).Render()
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<div class="e-float-input e-control-wrapper">
@Html.TextArea("ShipAddress")
<span class="e-float-line"></span>
<label asp-for="ShipAddress" class="e-float-text e-label-top">Ship Address</label>
</div>
</div>
</div>
</div>
@Html.EJS().ScriptManager()
@using Syncfusion.EJ2;
<div>
<div class="form-row">
<div class="form-group col-md-6">
<div class="e-float-input e-control-wrapper">
<input asp-for="OrderID" name="OrderID" value=@Model.OrderID.ToString() disabled type='text' />
<span class="e-float-line"></span>
<label asp-for="OrderID" class="e-float-text e-label-top">Order ID</label>
</div>
</div>
<div class="form-group col-md-6">
<div class="e-float-input e-control-wrapper">
<input asp-for="CustomerID" name="CustomerID" value=@Model.CustomerID />
<span class="e-float-line"></span>
<label asp-for="CustomerID" class="e-float-text e-label-top">Customer Name</label>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
@Html.EJS().NumericTextBox("Freight").Value(Model.Freight).Format("C2").Placeholder("Freight").FloatLabelType(Syncfusion.EJ2.Inputs.FloatLabelType.Always).Render()
</div>
<div class="form-group col-md-6">
@Html.EJS().DatePicker("OrderDate").Value(Model.OrderDate).Placeholder("Order Date").FloatLabelType(Syncfusion.EJ2.Inputs.FloatLabelType.Always).Render()
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
@Html.EJS().DropDownList("ShipCountry").DataSource(ViewBag.dataSource).Value(Model.ShipCountry).Placeholder("Ship Country").Fields(new Syncfusion.EJ2.DropDowns.DropDownListFieldSettings { Text = "ShipCountry", Value = "ShipCountry" }).FloatLabelType(Syncfusion.EJ2.Inputs.FloatLabelType.Always).Render()
</div>
<div class="form-group col-md-6">
@Html.EJS().DropDownList("ShipCity").DataSource(ViewBag.dataSource).Value(Model.ShipCity).Placeholder("Ship City").Fields(new Syncfusion.EJ2.DropDowns.DropDownListFieldSettings { Text = "ShipCity", Value = "ShipCity" }).FloatLabelType(Syncfusion.EJ2.Inputs.FloatLabelType.Always).Render()
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<div class="e-float-input e-control-wrapper">
@Html.TextArea("ShipAddress")
<span class="e-float-line"></span>
<label asp-for="ShipAddress" class="e-float-text e-label-top">Ship Address</label>
</div>
</div>
</div>
</div>
@Html.EJS().ScriptManager()
public IActionResult Index()
{
ViewBag.DataSource =OrderDetails.GetAllRecords();
return View();
}
public ActionResult Editpartial(DialogTemplateModel value)
{
ViewBag.datasource = OrdersDetails.GetAllRecords();
return PartialView("EditPartial", value);
}
public ActionResult AddPartial()
{
ViewBag.datasource = OrdersDetails.GetAllRecords();
return PartialView("AddPartial");
}
public class DialogTemplateModel
{
[Required]
public int? OrderID { get; set; }
[Required, MinLength(3)]
public string CustomerID { get; set; }
public int? EmployeeID { get; set; }
public double Freight { get; set; }
public string ShipCity { get; set; }
public bool Verified { get; set; }
public DateTime OrderDate { get; set; }
public string ShipName { get; set; }
public string ShipCountry { get; set; }
public DateTime ShippedDate { get; set; }
public string ShipAddress { get; set; }
}
Add | Edit |
---|---|
![]() |
![]() |
The template form editors should have name attribute.
Using template context
You can enhance the customization of your grid’s edit forms by utilizing template contexts, such as accessing row details inside template, rendering editors as components, getting values from editors, setting focus to editors, and disabling default form validation, and adding custom validation. These features are applicable in both inline and dialog editing modes.
The following template context topics are demonstrated through a practical example in the Render tab component inside the dialog template topic.
Access row details inside template using template context
When utilizing edit templates in the Grid , you can access crucial row information within an template when utilizing edit templates. This enables dynamic binding of attributes, values, or elements based on the specific row being edited. This is particularly useful for conditionally rendering or modifying elements in the edit template based on the row’s state.
The following properties will be available at the time of template execution:
Property Name | Usage |
---|---|
isAdd | A Boolean property that defines whether the current row is a new record or not. |
The following code example demonstrates the usage of the IsAdd
property in an edit template to disable the OrderID textbox when it’s not a new record:
<input id="OrderID" name="OrderID" type="text" value=${if(isAdd)} '' ${else} ${OrderID} ${/if} ${if(isAdd)}'' ${else} disabled ${/if}/>
Render editors as components
The Syncfusion Grid provides a powerful feature that allows you to dynamically render Syncfusion EJ2 controls as form editors during the editing process. This functionality is particularly useful when you want to provide feature-rich controls for data entry within the edit form.
To achieve this by utilizing the ActionComplete event of the Grid and specifying requestType
as beginEdit or add.
The following code example illustrates rendering the DropDownList component in the ActionComplete
event.
function actionComplete(args) {
if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
var countryData = ej.data.DataUtil.distinct(@Html.Raw(JsonConvert.SerializeObject(ViewBag.dataSource)), 'ShipCountry', true);;
new DropDownList({value: args.rowData.ShipCountry, popupHeight: '200px', floatLabelType: 'Always',
dataSource: countryData, fields: {text: 'ShipCountry', value: 'ShipCountry'}, placeholder: 'Ship Country'}, args.form.elements.namedItem('ShipCountry'));
}
}
Get value from editor
The get value from editor feature in the Syncfusion Grid allows you to read, format, and update the current editor value before it is saved. This feature is particularly valuable when you need to perform specific actions on the data, such as formatting or validation, before it is committed to the underlying data source.
To achieve this feature, you can utilize the ActionBegin event with the requestType set to save.
In the following code example, the freight value has been formatted and updated.
function actionBegin(args) {
if (args.requestType === 'save') {
// cast string to integer value.
args.data['Freight'] = parseFloat(args.form.querySelector("#Freight").value);
}
}
Set focus to particular column editor
The Syncfusion Grid allows you to control the focus behavior of input elements in edit forms. By default, the first input element in the dialog receives focus when the dialog is opened. However, in scenarios where the first input element is disabled or hidden, you can specify which valid input element should receive focus. This can be achieved using the ActionComplete event of the Grid, where the requestType is set to beginEdit.
In the following code example, the CustomerID column focused.
function actionComplete(args) {
// Set initail Focus
if (args.requestType === 'beginEdit') {
(args.form.elements.namedItem('CustomerID')).focus();
}
}
Disable default form validation
The Syncfusion Grid provides built-in support for vue form validation to ensure data integrity and accuracy during editing. However, there might be scenarios where you want to disable the default form validation rules. This can be achieved using the removeRules
method within the ActionComplete event of the Grid.
To disable default form validation rules in the Grid, follow these steps:
function actionComplete: (args) {
if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
// Disable the Validation Rules
args.form.ej2_instances[0].removeRules();
}
}
- You can use this method to disable validation rules: args.form.ej2_instances[0].rules = {}.
Adding validation rules for custom editors
The Syncfusion Grid provides the ability to add validation rules for fields that are not present in the column model. This feature is particularly useful to prevent erroneous or inconsistent data from being submitted, ultimately enhancing the reliability of your application’s data.
To accomplish this, you can utilize the ActionComplete event along with the addRules
method.
Here’s how you can use the addRules
method to add validation rules for custom editors in the actionComplete
event:
function actionComplete(args) {
if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
// Add Validation Rules
args.form.ej2_instances[0].addRules('Freight', {max: 500});
}
}
Render tab control inside the dialog template
You can enhance the editing experience in the Grid by rendering a Tab component inside the dialog template. This feature is especially useful when you want to present multiple editing sections or categories in a tabbed layout, ensuring a more intuitive and easily navigable interface for data editing.
To enable this functionality, you need to set the EditSettings.Mode property of the Grid to Dialog. This configures the Grid to use the dialog editing mode. Additionally, you can use the EditSettings.Template property to define a template variable that contains the Tab
component and its corresponding content.
The following example renders a tab component inside the edit dialog. The tab component has two tabs, and once you fill in the first tab and navigate to the second one, the validation for the first tab is performed before navigating to the second.
@Html.EJS().Grid("grid").DataSource((IEnumerable<object>)ViewBag.DataSource).ActionComplete("actionComplete").Height("348px").Columns(col =>
{
col.Field("OrderID").HeaderText("Order ID").IsPrimaryKey(true).Width("120").ValidationRules(new { required = true }).TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Add();
col.Field("CustomerID").HeaderText("Customer Name").Width("150").ValidationRules(new { required = true, minLength = 3 }).Add();
col.Field("Freight").HeaderText("Freight").Width("150").TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Add();
col.Field("ShipCountry").HeaderText("Ship Country").Width("150").Add();
col.Field("ShipAddress").HeaderText("Ship Address").Width("150").Add();
col.Field("Verified").HeaderText("Verified").Width("150").TextAlign(Syncfusion.EJ2.Grids.TextAlign.Center).Type("boolean").DisplayAsCheckBox(true).Add();
}).AllowPaging().EditSettings(edit => { edit.AllowAdding(true).AllowEditing(true).AllowDeleting(true).Mode(Syncfusion.EJ2.Grids.EditMode.Dialog).Template("#dialogtemplate"); }).Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" }).Render()
<script id="dialogtemplate" type="text/x-template">
<div>
<div id="edittab"></div>
<div id="tab1">
<div class="form-row">
<div class="form-group col-md-6">
<div class="e-float-input e-control-wrapper">
<input id="OrderID" required name="OrderID" type="text" value=${if(isAdd)} '' ${else} ${OrderID} ${ /if} ${if(isAdd)} '' ${else} disabled ${ /if} />
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="OrderID">Order ID</label>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<div class="e-float-input e-control-wrapper">
<input id="CustomerID" required name="CustomerID" type="text" value=${if(isAdd)} '' ${else} ${CustomerID} ${ /if} />
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="CustomerID">Customer ID</label>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<input type="text" required name="ShipCountry" id="ShipCountry" value=${if(isAdd)} '' ${else} ${ShipCountry} ${ /if} />
</div>
</div>
<button id='next' class='e-info e-btn' style="float: right" type='button'> next</button>
</div>
<div id="tab2" style='display: none'>
<div class="form-row">
<div class="form-group col-md-6">
<input type="text" required name="Freight" id="Freight" value=${if(isAdd)} '' ${else} ${Freight} ${ /if} />
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<textarea name="ShipAddress" id="ShipAddress"></textarea>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<input type="checkbox" name="Verified" id="Verified" ${if(isAdd)} '' ${else} checked ${ /if} />
</div>
</div>
<button id='submit' class='e-info e-btn' style="float: right" type='button'> submit</button>
</div>
</div>
</script>
<script>
var countryData = ej.data.DataUtil.distinct(@Html.Raw(JsonConvert.SerializeObject(ViewBag.dataSource)), 'ShipCountry', true);;
function actionComplete(args) {
var grid = document.getElementById('grid').ej2_instances[0];
if ( args.dialog && args.dialog.element && args.dialog.element.querySelector(".e-footer-content")) {
args.dialog.element.querySelector(".e-footer-content").classList.add("e-hide");
}
if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
var tabObject = new ej.navigations.Tab({
showCloseButton: false,
selecting: (e) => {if(e.isSwiped) {e.cancel = true;} if(e.selectingIndex === 1) {e.cancel = !validate(1)}},
items: [
{ header: { 'text': 'Details' }, content: '#tab1' },
{ header: { 'text': 'Verify' }, content: '#tab2' },
]
});
tabObject.appendTo('#edittab');
args.form.ej2_instances[0].removeRules();
args.form.ej2_instances[0].addRules("Freight", { min: 1, max: 500 });
new ej.dropdowns.DropDownList({value: args.rowData.ShipCountry, popupHeight: '200px', floatLabelType: 'Always',
dataSource: countryData, fields: {text: 'ShipCountry', value: 'ShipCountry'}, placeholder: 'Ship Country'}, args.form.elements.namedItem('ShipCountry'));
new ej.inputs.NumericTextBox({value: args.rowData.Freight, floatLabelType: 'Always', placeholder: 'Freight'}, args.form.elements.namedItem('Freight'));
new ej.inputs.TextArea({ value: args.rowData.ShipAddress,floatLabelType: 'Always',resizeMode: 'Both',width:"250px",placeholder: 'Ship Address'}, args.form.elements.namedItem('ShipAddress'));
new ej.buttons.CheckBox({ label: 'Verified', checked: args.rowData.Verified }, args.form.elements.namedItem('Verified'));
if (args.requestType === 'beginEdit') {
(args.form.elements.namedItem('CustomerID')).focus();
}
document.getElementById('next').onclick = () => {
moveNext();
}
function validate(tab) {
let valid = true;
[].slice.call(document.getElementById('tab' + tab).querySelectorAll('[name]')).forEach(element => {
setTimeout(() => {
if ( element.form && element.form.ej2_instances && element.form.ej2_instances.length > 0) {
element.form.ej2_instances[0].validate(element.name); }
}, 100);
if (element.getAttribute('aria-invalid') === 'true'){
valid = false;
}
});
if (!valid) {
return false;
}
return true;
}
function moveNext() {
if (validate(1)) {
tabObject.select(1);
}
}
document.getElementById('submit').onclick = () => {
if (validate(2)) {
grid.endEdit();
}
}
}
}
</script>
<style>
.form-group.col-md-6 {
width: 250px;
margin-bottom: 20px
}
</style>
public IActionResult Index()
{
ViewBag.DataSource = OrderDetails.GetAllRecords();
return View();
}