Skip to content

Commit 296ed1c

Browse files
docs(Grid): Revamp Popup Form Template example (#2956)
Co-authored-by: Dimo Dimov <961014+dimodi@users.noreply.github.com>
1 parent 58014b7 commit 296ed1c

File tree

1 file changed

+164
-125
lines changed

1 file changed

+164
-125
lines changed

components/grid/templates/popup-form-template.md

+164-125
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ With the `FormTemplate` feature, you can customize the appearance and content of
2727
## Specifics
2828

2929
When using the template, the default Popup form is replaced by the declared content within the `FormTemplate` tag. This introduces the following specifics:
30-
* The default **Update** and **Cancel** buttons are removed. This means that the [`OnUpdate` and `OnCancel`](slug:grid-editing-overview#events) events cannot be triggered. To modify or cancel the update of a record, you need to include custom controls to manage these actions.
30+
31+
* The default **Update** and **Cancel** buttons are removed. This means that the [`OnUpdate` and `OnCancel`](slug:grid-editing-overview#events) events do not fire. To modify or cancel the update of a record, you need to include custom components to manage these actions.
3132
* The popup footer remains empty by design. You can [either hide it or place your custom buttons in it](slug:grid-kb-handle-empty-popup-footer).
3233
* The `FormTemplate` disables the [built-in validation](slug:grid-editing-validation) of the Grid. Implement a [Form Validation](slug:form-validation) instead.
3334
* The [`<GridPopupEditFormSettings>` parameters](slug:grid-editing-popup#form-layout) do not apply to a custom `TelerikForm` that you may render inside the `<FormTemplate>` tag. Set the desired Form configurations such as `Columns`, `Orientation`, and more on the [Form component](slug:form-overview#form-parameters).
@@ -37,200 +38,238 @@ When using the template, the default Popup form is replaced by the declared cont
3738
Using a `FormTemplate` to modify the Edit/Create Popup window.
3839

3940
````RAZOR
40-
@using System.Collections.Generic;
41+
@using System.ComponentModel.DataAnnotations
4142
@using Telerik.DataSource
4243
@using Telerik.DataSource.Extensions
4344
4445
<TelerikGrid @ref="@GridRef"
45-
Data="@GridData"
46+
OnRead="@OnGridRead"
47+
TItem="@Product"
4648
EditMode="@GridEditMode.Popup"
47-
Pageable="true"
48-
Width="950px"
49-
PageSize="5"
50-
OnDelete="@DeleteItem">
49+
OnDelete="@OnGridDelete">
5150
<GridToolBarTemplate>
52-
<GridCommandButton Command="Add" Icon="@SvgIcon.Plus">Add Employee</GridCommandButton>
51+
<GridCommandButton Command="Add">Add Item</GridCommandButton>
5352
</GridToolBarTemplate>
5453
<GridSettings>
5554
<GridPopupEditSettings Width="550px" MaxHeight="95vh" MaxWidth="95vw"></GridPopupEditSettings>
56-
<GridPopupEditFormSettings Context="FormContext">
55+
<GridPopupEditFormSettings Context="formContext">
5756
<FormTemplate>
5857
@{
59-
EditItem = FormContext.Item as Person;
60-
61-
<TelerikForm Model="@EditItem"
58+
if (GridEditItem is null)
59+
{
60+
// Setting GridEditItem unconditionally may
61+
// reset the modified and unsaved values after re-render.
62+
// Nullify GridEditItem when editing completes.
63+
GridEditItem = (Product)formContext.Item;
64+
}
65+
66+
<TelerikForm Model="@GridEditItem"
6267
ColumnSpacing="20px"
6368
Columns="2"
6469
ButtonsLayout="@FormButtonsLayout.Stretch"
65-
OnValidSubmit="@OnValidSubmit">
70+
OnValidSubmit="@OnFormValidSubmit">
6671
<FormItems>
67-
<FormItem Field="EmployeeId" Enabled="false"></FormItem>
68-
<FormItem Field="Name">
69-
</FormItem>
70-
<FormItem Field="HireDate" LabelText="Custom Hire Date Label"></FormItem>
71-
<FormItem>
72+
<FormItem Field="@nameof(Product.Id)" Enabled="false" />
73+
<FormItem Field="@nameof(Product.Name)" />
74+
<FormItem Field="@nameof(Product.Description)"
75+
ColSpan="2"
76+
EditorType="@FormEditorType.TextArea" />
77+
<FormItem Field="@nameof(Product.Price)">
7278
<Template>
73-
<label for="position">Custom Position Label</label>
74-
<TelerikDropDownList Data="@PositionsData"
75-
@bind-Value="@EditItem.Position"
76-
Id="position">
77-
</TelerikDropDownList>
79+
<label class="k-label k-form-label">Price</label>
80+
<div class="k-form-field-wrap">
81+
<TelerikNumericTextBox @bind-Value="@GridEditItem.Price"
82+
DebounceDelay="0" />
83+
<TelerikValidationMessage For="@( () => GridEditItem.Price)" />
84+
</div>
7885
</Template>
7986
</FormItem>
80-
</FormItems>
81-
<FormButtons>
82-
<TelerikButton Icon="@nameof(SvgIcon.Save)">Save</TelerikButton>
83-
<TelerikButton Icon="@nameof(SvgIcon.Cancel)" ButtonType="@ButtonType.Button" OnClick="@OnCancel">Cancel</TelerikButton>
84-
</FormButtons>
85-
</TelerikForm>
87+
<FormItem Field="@nameof(Product.Quantity)" />
88+
<FormItem Field="@nameof(Product.ReleaseDate)" />
89+
<FormItem Field="@nameof(Product.Discontinued)" />
90+
</FormItems>
91+
<FormButtons>
92+
<TelerikButton Icon="@nameof(SvgIcon.Save)">Save</TelerikButton>
93+
<TelerikButton Icon="@nameof(SvgIcon.Cancel)"
94+
ButtonType="@ButtonType.Button"
95+
OnClick="@ExitGridEditMode">Cancel</TelerikButton>
96+
</FormButtons>
97+
</TelerikForm>
8698
}
8799
</FormTemplate>
88100
</GridPopupEditFormSettings>
89101
</GridSettings>
90102
<GridColumns>
91-
<GridColumn Field=@nameof(Person.EmployeeId) Editable="false" />
92-
<GridColumn Field=@nameof(Person.Name) />
93-
<GridColumn Field=@nameof(Person.HireDate) Title="Hire Date" />
94-
<GridColumn Field=@nameof(Person.Position) Title="Position" />
95-
<GridCommandColumn>
96-
<GridCommandButton Command="Edit" Icon="@SvgIcon.Pencil">Edit</GridCommandButton>
97-
<GridCommandButton Command="Delete" Icon="@SvgIcon.Trash">Delete</GridCommandButton>
103+
<GridColumn Field="@nameof(Product.Name)" />
104+
<GridColumn Field="@nameof(Product.Price)" DisplayFormat="{0:C2}" />
105+
<GridColumn Field="@nameof(Product.Quantity)" DisplayFormat="{0:N0}" />
106+
<GridColumn Field="@nameof(Product.ReleaseDate)" DisplayFormat="{0:d}" />
107+
<GridColumn Field="@nameof(Product.Discontinued)" Width="120px" />
108+
<GridCommandColumn Width="180px">
109+
<GridCommandButton Command="Edit">Edit</GridCommandButton>
110+
<GridCommandButton Command="Delete">Delete</GridCommandButton>
98111
</GridCommandColumn>
99112
</GridColumns>
100113
</TelerikGrid>
101114
102115
@code {
103-
private List<string> PositionsData { get; set; } = new List<string>()
104-
{
105-
"Manager", "Developer", "QA"
106-
};
116+
private ProductService GridProductService { get; set; } = new();
107117
108-
private TelerikGrid<Person> GridRef { get; set; }
109-
private List<Person> GridData { get; set; }
110-
private Person EditItem { get; set; }
111-
private List<Person> _people;
118+
private TelerikGrid<Product>? GridRef { get; set; }
112119
113-
public class Person
114-
{
115-
public int EmployeeId { get; set; }
116-
public string Name { get; set; }
117-
public DateTime HireDate { get; set; }
118-
public string Position { get; set; }
119-
}
120+
private Product? GridEditItem { get; set; }
120121
121-
public List<Person> People
122+
private async Task OnFormValidSubmit()
122123
{
123-
get
124+
if (GridEditItem is null)
124125
{
125-
if (_people == null)
126-
{
127-
_people = GeneratePeople(30);
128-
}
126+
return;
127+
}
129128
130-
return _people;
129+
if (GridEditItem.Id != default)
130+
{
131+
await GridProductService.Update(GridEditItem);
132+
}
133+
else
134+
{
135+
await GridProductService.Create(GridEditItem);
131136
}
137+
138+
await ExitGridEditMode();
132139
}
133140
134-
protected override void OnInitialized()
141+
private async Task ExitGridEditMode()
135142
{
136-
LoadData();
143+
if (GridRef is null)
144+
{
145+
return;
146+
}
147+
148+
var state = GridRef.GetState();
149+
state.OriginalEditItem = null!;
150+
state.EditItem = null!;
151+
state.InsertedItem = null!;
152+
153+
await GridRef.SetStateAsync(state);
154+
155+
GridEditItem = default;
137156
}
138157
139-
private void LoadData()
158+
private async Task OnGridDelete(GridCommandEventArgs args)
140159
{
141-
GridData = GetPeople();
160+
var deletedItem = (Product)args.Item;
161+
162+
await GridProductService.Delete(deletedItem);
142163
}
143164
144-
private void DeleteItem(GridCommandEventArgs args)
165+
private async Task OnGridRead(GridReadEventArgs args)
145166
{
146-
DeletePerson(args.Item as Person);
167+
DataSourceResult result = await GridProductService.Read(args.Request);
147168
148-
LoadData();
169+
args.Data = result.Data;
170+
args.Total = result.Total;
171+
args.AggregateResults = result.AggregateResults;
149172
}
150173
151-
private async Task OnValidSubmit()
174+
public class Product
152175
{
176+
public int Id { get; set; }
177+
[Required]
178+
public string Name { get; set; } = string.Empty;
179+
public string Description { get; set; } = string.Empty;
180+
public decimal? Price { get; set; }
181+
public int Quantity { get; set; }
182+
[Required]
183+
public DateTime? ReleaseDate { get; set; }
184+
public bool Discontinued { get; set; }
185+
}
153186
154-
if (EditItem.EmployeeId != default)
155-
{
156-
UpdatePerson(EditItem);
157-
}
158-
else
187+
#region Data Service
188+
189+
public class ProductService
190+
{
191+
private List<Product> Items { get; set; } = new();
192+
193+
private int LastId { get; set; }
194+
195+
public async Task<int> Create(Product product)
159196
{
160-
CreatePerson(EditItem);
161-
}
197+
await SimulateAsyncOperation();
162198
163-
await ExitEditAsync();
199+
product.Id = ++LastId;
164200
165-
LoadData();
166-
}
201+
Items.Insert(0, product);
167202
168-
private async Task OnCancel()
169-
{
170-
await ExitEditAsync();
171-
}
203+
return LastId;
204+
}
172205
173-
private async Task ExitEditAsync()
174-
{
175-
var state = GridRef?.GetState();
176-
state.OriginalEditItem = null;
177-
state.EditItem = null;
178-
state.InsertedItem = null;
206+
public async Task<bool> Delete(Product product)
207+
{
208+
await SimulateAsyncOperation();
179209
180-
await GridRef?.SetStateAsync(state);
181-
}
210+
if (Items.Contains(product))
211+
{
212+
Items.Remove(product);
182213
183-
#region Service Methods
184-
private List<Person> GetPeople()
185-
{
186-
return People;
187-
}
214+
return true;
215+
}
188216
189-
private DataSourceResult GetPeople(DataSourceRequest request)
190-
{
191-
return People.ToDataSourceResult(request);
192-
}
217+
return false;
218+
}
193219
194-
private void DeletePerson(Person person)
195-
{
196-
People.Remove(person);
197-
}
220+
public async Task<List<Product>> Read()
221+
{
222+
await SimulateAsyncOperation();
198223
199-
private void UpdatePerson(Person person)
200-
{
201-
var index = People.FindIndex(i => i.EmployeeId == person.EmployeeId);
202-
if (index != -1)
224+
return Items;
225+
}
226+
227+
public async Task<DataSourceResult> Read(DataSourceRequest request)
203228
{
204-
People[index] = person;
229+
return await Items.ToDataSourceResultAsync(request);
205230
}
206-
}
207231
208-
private void CreatePerson(Person person)
209-
{
210-
person.EmployeeId = People.Max(x => x.EmployeeId) + 1;
232+
public async Task<bool> Update(Product product)
233+
{
234+
await SimulateAsyncOperation();
211235
212-
People.Insert(0, person);
213-
}
236+
int originalItemIndex = Items.FindIndex(x => x.Id == product.Id);
214237
215-
private List<Person> GeneratePeople(int count, int startIndex = 0)
216-
{
217-
List<Person> result = new List<Person>();
238+
if (originalItemIndex != -1)
239+
{
240+
Items[originalItemIndex] = product;
241+
return true;
242+
}
243+
244+
return false;
245+
}
218246
219-
for (int i = startIndex; i < startIndex + count; i++)
247+
private async Task SimulateAsyncOperation()
220248
{
221-
result.Add(new Person()
222-
{
223-
EmployeeId = i,
224-
Name = "Employee " + i.ToString(),
225-
HireDate = new DateTime(2020, 6, 1).Date.AddDays(count - (i % 7)),
226-
Position = i % 3 <= 2 ? PositionsData[i % 3] : PositionsData.FirstOrDefault()
249+
await Task.Delay(100);
250+
}
251+
252+
public ProductService(int itemCount = 5)
253+
{
254+
Random rnd = Random.Shared;
227255
256+
for (int i = 1; i <= itemCount; i++)
257+
{
258+
Items.Add(new Product()
259+
{
260+
Id = ++LastId,
261+
Name = $"Product {LastId}",
262+
Description = $"Multi-line\ndescription {LastId}",
263+
Price = LastId % 2 == 0 ? null : rnd.Next(0, 100) * 1.23m,
264+
Quantity = LastId % 2 == 0 ? 0 : rnd.Next(0, 3000),
265+
ReleaseDate = DateTime.Today.AddDays(-rnd.Next(365, 3650)),
266+
Discontinued = LastId % 2 == 0
228267
});
268+
}
229269
}
230-
231-
return result;
232270
}
233-
#endregion
271+
272+
#endregion Data Service
234273
}
235274
````
236275

0 commit comments

Comments
 (0)