@@ -27,7 +27,8 @@ With the `FormTemplate` feature, you can customize the appearance and content of
27
27
## Specifics
28
28
29
29
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.
31
32
* 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 ) .
32
33
* The ` FormTemplate ` disables the [ built-in validation] ( slug:grid-editing-validation ) of the Grid. Implement a [ Form Validation] ( slug:form-validation ) instead.
33
34
* 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
37
38
Using a ` FormTemplate ` to modify the Edit/Create Popup window.
38
39
39
40
```` RAZOR
40
- @using System.Collections.Generic;
41
+ @using System.ComponentModel.DataAnnotations
41
42
@using Telerik.DataSource
42
43
@using Telerik.DataSource.Extensions
43
44
44
45
<TelerikGrid @ref="@GridRef"
45
- Data="@GridData"
46
+ OnRead="@OnGridRead"
47
+ TItem="@Product"
46
48
EditMode="@GridEditMode.Popup"
47
- Pageable="true"
48
- Width="950px"
49
- PageSize="5"
50
- OnDelete="@DeleteItem">
49
+ OnDelete="@OnGridDelete">
51
50
<GridToolBarTemplate>
52
- <GridCommandButton Command="Add" Icon="@SvgIcon.Plus" >Add Employee </GridCommandButton>
51
+ <GridCommandButton Command="Add">Add Item </GridCommandButton>
53
52
</GridToolBarTemplate>
54
53
<GridSettings>
55
54
<GridPopupEditSettings Width="550px" MaxHeight="95vh" MaxWidth="95vw"></GridPopupEditSettings>
56
- <GridPopupEditFormSettings Context="FormContext ">
55
+ <GridPopupEditFormSettings Context="formContext ">
57
56
<FormTemplate>
58
57
@{
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"
62
67
ColumnSpacing="20px"
63
68
Columns="2"
64
69
ButtonsLayout="@FormButtonsLayout.Stretch"
65
- OnValidSubmit="@OnValidSubmit ">
70
+ OnValidSubmit="@OnFormValidSubmit ">
66
71
<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)">
72
78
<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>
78
85
</Template>
79
86
</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>
86
98
}
87
99
</FormTemplate>
88
100
</GridPopupEditFormSettings>
89
101
</GridSettings>
90
102
<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>
98
111
</GridCommandColumn>
99
112
</GridColumns>
100
113
</TelerikGrid>
101
114
102
115
@code {
103
- private List<string> PositionsData { get; set; } = new List<string>()
104
- {
105
- "Manager", "Developer", "QA"
106
- };
116
+ private ProductService GridProductService { get; set; } = new();
107
117
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; }
112
119
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; }
120
121
121
- public List<Person> People
122
+ private async Task OnFormValidSubmit()
122
123
{
123
- get
124
+ if (GridEditItem is null)
124
125
{
125
- if (_people == null)
126
- {
127
- _people = GeneratePeople(30);
128
- }
126
+ return;
127
+ }
129
128
130
- return _people;
129
+ if (GridEditItem.Id != default)
130
+ {
131
+ await GridProductService.Update(GridEditItem);
132
+ }
133
+ else
134
+ {
135
+ await GridProductService.Create(GridEditItem);
131
136
}
137
+
138
+ await ExitGridEditMode();
132
139
}
133
140
134
- protected override void OnInitialized ()
141
+ private async Task ExitGridEditMode ()
135
142
{
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;
137
156
}
138
157
139
- private void LoadData( )
158
+ private async Task OnGridDelete(GridCommandEventArgs args )
140
159
{
141
- GridData = GetPeople();
160
+ var deletedItem = (Product)args.Item;
161
+
162
+ await GridProductService.Delete(deletedItem);
142
163
}
143
164
144
- private void DeleteItem(GridCommandEventArgs args)
165
+ private async Task OnGridRead(GridReadEventArgs args)
145
166
{
146
- DeletePerson (args.Item as Person );
167
+ DataSourceResult result = await GridProductService.Read (args.Request );
147
168
148
- LoadData();
169
+ args.Data = result.Data;
170
+ args.Total = result.Total;
171
+ args.AggregateResults = result.AggregateResults;
149
172
}
150
173
151
- private async Task OnValidSubmit()
174
+ public class Product
152
175
{
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
+ }
153
186
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)
159
196
{
160
- CreatePerson(EditItem);
161
- }
197
+ await SimulateAsyncOperation();
162
198
163
- await ExitEditAsync() ;
199
+ product.Id = ++LastId ;
164
200
165
- LoadData();
166
- }
201
+ Items.Insert(0, product);
167
202
168
- private async Task OnCancel()
169
- {
170
- await ExitEditAsync();
171
- }
203
+ return LastId;
204
+ }
172
205
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();
179
209
180
- await GridRef?.SetStateAsync(state);
181
- }
210
+ if (Items.Contains(product))
211
+ {
212
+ Items.Remove(product);
182
213
183
- #region Service Methods
184
- private List<Person> GetPeople()
185
- {
186
- return People;
187
- }
214
+ return true;
215
+ }
188
216
189
- private DataSourceResult GetPeople(DataSourceRequest request)
190
- {
191
- return People.ToDataSourceResult(request);
192
- }
217
+ return false;
218
+ }
193
219
194
- private void DeletePerson(Person person)
195
- {
196
- People.Remove(person);
197
- }
220
+ public async Task<List<Product>> Read()
221
+ {
222
+ await SimulateAsyncOperation();
198
223
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 )
203
228
{
204
- People[index] = person ;
229
+ return await Items.ToDataSourceResultAsync(request) ;
205
230
}
206
- }
207
231
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() ;
211
235
212
- People.Insert(0, person);
213
- }
236
+ int originalItemIndex = Items.FindIndex(x => x.Id == product.Id);
214
237
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
+ }
218
246
219
- for (int i = startIndex; i < startIndex + count; i++ )
247
+ private async Task SimulateAsyncOperation( )
220
248
{
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;
227
255
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
228
267
});
268
+ }
229
269
}
230
-
231
- return result;
232
270
}
233
- #endregion
271
+
272
+ #endregion Data Service
234
273
}
235
274
````
236
275
0 commit comments