Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(Grid): Revamp Editing documentation #2787

Merged
merged 33 commits into from
Mar 11, 2025
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
5b4b8f5
docs(Grid): Revamp Editing articles
dimodi Jan 31, 2025
987284d
continued
dimodi Feb 11, 2025
84a8603
Revamp continued
dimodi Feb 15, 2025
5d95a2b
Revamp continued
dimodi Feb 15, 2025
7ecde95
Revamp continued
dimodi Feb 16, 2025
cd165e5
Revamp continued
dimodi Feb 17, 2025
7a1c622
Revamp continued
dimodi Feb 19, 2025
9ce9702
Revamp continued
dimodi Feb 20, 2025
6ae121e
Revamp continued
dimodi Feb 22, 2025
21aac10
Revamp continued
dimodi Feb 22, 2025
67fb999
Revamp continued
dimodi Feb 23, 2025
de359aa
polishing
dimodi Feb 25, 2025
1b172e4
Replace TreeList Inline Edit example
dimodi Feb 28, 2025
431acca
refactor code
dimodi Mar 1, 2025
78fc766
Add ConfirmDelete
dimodi Mar 1, 2025
4bfb921
docs(TreeList): Revamp CRUD articles
dimodi Mar 1, 2025
c957980
fix redirects
dimodi Mar 1, 2025
fbc406a
Update components/grid/editing/overview.md
dimodi Mar 1, 2025
a449f03
Update components/grid/editing/overview.md
dimodi Mar 1, 2025
222591e
Update components/grid/editing/overview.md
dimodi Mar 1, 2025
5257338
Update components/grid/editing/overview.md
dimodi Mar 1, 2025
33860e4
Update components/grid/editing/overview.md
dimodi Mar 1, 2025
bade2d7
Update components/grid/editing/overview.md
dimodi Mar 1, 2025
70f9163
Update components/grid/editing/overview.md
dimodi Mar 1, 2025
0d947a4
Update components/grid/editing/overview.md
dimodi Mar 1, 2025
4043526
Update components/grid/editing/incell.md
dimodi Mar 1, 2025
937beaf
Update components/grid/loading-animation.md
dimodi Mar 1, 2025
25fa688
Address PR suggestions
dimodi Mar 1, 2025
729fceb
Fix letter casing
dimodi Mar 1, 2025
fbf6c5b
Remove extra tag
dimodi Mar 1, 2025
2b8e874
Revamp TreeList State article
dimodi Mar 2, 2025
6ae5f0a
Update knowledge-base/grid-popup-edit-form-columns.md
dimodi Mar 11, 2025
b9a55a6
Add Grid Overview links to CRUD pages
dimodi Mar 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _contentTemplates/common/general-info.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ If you set the `ShouldRender` field of the event arguments to `true`, the compon
| tb-gantt-editable | [Gantt with Editing](slug:gantt-tree-editing) |
| tb-ganttcolumn | [Gantt - Databound Column](slug:gantt-columns-bound) |
| tb-grid | [Grid](slug:grid-overview) |
| tb-grid-editable | [Grid with Editing](slug:components/grid/editing/overview) |
| tb-grid-editable | [Grid with Editing](slug:grid-editing-overview) |
| tb-gridcolumn | [Grid - Databound Column](slug:components/grid/columns/bound) |
| tb-gridcolumn-locked | [Grid with Frozen Column](slug:grid-columns-frozen) |
| tb-gridlayout | [GridLayout](slug:gridlayout-overview) |
Expand Down
10 changes: 0 additions & 10 deletions _contentTemplates/common/grid-treelist-editing-notes.md

This file was deleted.

2 changes: 1 addition & 1 deletion _contentTemplates/common/parameters-table-styles.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#table-layout
<style>
article table {
.article table {
table-layout: auto;
word-break: normal;
}
Expand Down
332 changes: 332 additions & 0 deletions _contentTemplates/grid/editing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,332 @@
#overview-required

> Make sure to read the [Grid CRUD Operations](slug:grid-editing-overview) article first.

#end

#without-commands

Without using the above command buttons, the application can:

* [Manage add or edit mode programmatically](slug:grid-kb-add-edit-state) through the [Grid state](slug:grid-state).
* Modify data items directly in the Grid data source. [Rebind the Grid](slug:common-features-data-binding-overview#refresh-data) afterwards.

#end

#basic-example-description
* Use the `OnCreate`, `OnDelete` and `OnUpdate` events to make changes to the Grid data source.
* Rebind the Grid automatically through the `OnRead` event after the create, delete, or update operation is complete. When [using the `Data` parameter, you must either query the data source again, or modify the local `Data` collection manually](#advanced).
* Use `DataAnnotations` validation for some model class properties.
#end

#basic-example-parameters-columns
OnCreate="@OnGridCreate"
OnDelete="@OnGridDelete"
OnUpdate="@OnGridUpdate">
<GridToolBarTemplate>
<GridCommandButton Command="Add">Add Item</GridCommandButton>
</GridToolBarTemplate>
<GridColumns>
<GridColumn Field="@nameof(Product.Name)" />
<GridColumn Field="@nameof(Product.Price)" DisplayFormat="{0:C2}" />
<GridColumn Field="@nameof(Product.Quantity)" DisplayFormat="{0:N0}" />
<GridColumn Field="@nameof(Product.ReleaseDate)" DisplayFormat="{0:d}" />
<GridColumn Field="@nameof(Product.Discontinued)" Width="120px" />
#end

#basic-example-code
private ProductService GridProductService { get; set; } = new();

private async Task OnGridCreate(GridCommandEventArgs args)
{
var createdItem = (Product)args.Item;

await GridProductService.Create(createdItem);
}

private async Task OnGridDelete(GridCommandEventArgs args)
{
var deletedItem = (Product)args.Item;

await GridProductService.Delete(deletedItem);
}

private async Task OnGridRead(GridReadEventArgs args)
{
DataSourceResult result = await GridProductService.Read(args.Request);

args.Data = result.Data;
args.Total = result.Total;
args.AggregateResults = result.AggregateResults;
}

private async Task OnGridUpdate(GridCommandEventArgs args)
{
var updatedItem = (Product)args.Item;

await GridProductService.Update(updatedItem);
}
#end

#crud-service-and-model
public class Product
{
public int Id { get; set; }
[Required]
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public decimal? Price { get; set; }
public int Quantity { get; set; }
[Required]
public DateTime? ReleaseDate { get; set; }
public bool Discontinued { get; set; }
}

#region Data Service

public class ProductService
{
private List<Product> Items { get; set; } = new();

private int LastId { get; set; }

public async Task<int> Create(Product product)
{
await SimulateAsyncOperation();

product.Id = ++LastId;

Items.Insert(0, product);

return LastId;
}

public async Task<bool> Delete(Product product)
{
await SimulateAsyncOperation();

if (Items.Contains(product))
{
Items.Remove(product);

return true;
}

return false;
}

public async Task<List<Product>> Read()
{
await SimulateAsyncOperation();

return Items;
}

public async Task<DataSourceResult> Read(DataSourceRequest request)
{
return await Items.ToDataSourceResultAsync(request);
}

public async Task<bool> Update(Product product)
{
await SimulateAsyncOperation();

int originalItemIndex = Items.FindIndex(x => x.Id == product.Id);

if (originalItemIndex != -1)
{
Items[originalItemIndex] = product;
return true;
}

return false;
}

private async Task SimulateAsyncOperation()
{
await Task.Delay(100);
}

public ProductService(int itemCount = 5)
{
Random rnd = Random.Shared;

for (int i = 1; i <= itemCount; i++)
{
Items.Add(new Product()
{
Id = ++LastId,
Name = $"Product {LastId}",
Description = $"Multi-line\ndescription {LastId}",
Price = LastId % 2 == 0 ? null : rnd.Next(0, 100) * 1.23m,
Quantity = LastId % 2 == 0 ? 0 : rnd.Next(0, 3000),
ReleaseDate = DateTime.Today.AddDays(-rnd.Next(365, 3650)),
Discontinued = LastId % 2 == 0
});
}
}
}

#endregion Data Service
#end

#advanced-example-description
* Use the `OnCreate`, `OnDelete` and `OnUpdate` events to make changes to the Grid data source.
* Use the `OnModelInit` event to provide [model instances](slug:grid-editing-overview#item-instances) with some default values before add and edit operations start.
* Use the `OnAdd` event to provide some default values before add operations start.
* Reload the Grid `Data` after making changes to the data source. When [using the Grid `OnRead` event, the component will fire `OnRead` and rebind automatically](#basic).
* Apply the user changes to the Grid `Data` parameter to spare one read request to the database.
* Use `DataAnnotations` validation for the `Name` and `ReleaseDate` properties.
* Define the `Id` column as non-editable.
* Customize the `Description` and `Discontinued` column editors without using an `EditorTemplate`.
* Render the **Delete** command button conditionally if `Discontinued` is `true`.
* Confirm **Delete** commands with the built-in Grid Dialog. You can also [intercept item deletion with a separate Dialog or a custom popup](slug:grid-kb-customize-delete-confirmation-dialog).
* Cancel the `OnAdd` and `OnEdit` events conditionally, so that the Grid does not go into edit mode.
* Cancel the `OnCancel` event conditionally, so that the Grid remains in edit mode and the user doesn't lose their unsaved changes.
#end

#advanced-example-parameters
OnAdd="@OnGridAdd"
OnCancel="@OnGridCancel"
OnCreate="@OnGridCreate"
OnDelete="@OnGridDelete"
OnEdit="@OnGridEdit"
OnModelInit="@OnGridModelInit"
OnUpdate="@OnGridUpdate"
Pageable="true"
PageSize="5"
Sortable="true">
#end

#advanced-example-toolbar
<GridToolBarTemplate>
<GridCommandButton Command="Add" ThemeColor="@AddEditButtonThemeColor">Add Item</GridCommandButton>
<span class="k-separator"></span>
<label class="k-checkbox-label"><TelerikCheckBox @bind-Value="@ShouldCancelOnAddEdit" /> Cancel OnAdd and OnEdit Events</label>
<span class="k-separator"></span>
<label class="k-checkbox-label"><TelerikCheckBox @bind-Value="@GridConfirmDelete" /> Confirm Delete Commands</label>
<span class="k-separator"></span>
<label class="k-checkbox-label"><TelerikCheckBox @bind-Value="@ShouldConfirmOnCancel" /> Confirm Cancel Commands</label>
</GridToolBarTemplate>
#end

#advanced-example-columns
<GridColumn Field="@nameof(Product.Price)" DisplayFormat="{0:C2}" />
<GridColumn Field="@nameof(Product.Quantity)" DisplayFormat="{0:N0}" />
<GridColumn Field="@nameof(Product.ReleaseDate)" DisplayFormat="{0:d}" />
<GridColumn Field="@nameof(Product.Discontinued)" Width="120px" EditorType="@GridEditorType.Switch" />
#end

#advanced-example-code
private List<Product> GridData { get; set; } = new();

private ProductService GridProductService { get; set; } = new();

[CascadingParameter]
public DialogFactory? TelerikDialogs { get; set; }

#region Example Settings

private bool GridConfirmDelete { get; set; } = true;
private bool ShouldCancelOnAddEdit { get; set; }
private bool ShouldConfirmOnCancel { get; set; } = true;

private string AddEditButtonThemeColor => ShouldCancelOnAddEdit ? ThemeConstants.Button.ThemeColor.Error : ThemeConstants.Button.ThemeColor.Base;
private string DeleteButtonThemeColor => GridConfirmDelete ? ThemeConstants.Button.ThemeColor.Base : ThemeConstants.Button.ThemeColor.Warning;
private string CancelButtonThemeColor => ShouldConfirmOnCancel ? ThemeConstants.Button.ThemeColor.Base : ThemeConstants.Button.ThemeColor.Warning;

#endregion Example Settings

#region Grid Events

private void OnGridAdd(GridCommandEventArgs args)
{
if (ShouldCancelOnAddEdit)
{
args.IsCancelled = true;
}

var newItem = (Product)args.Item;
newItem.Name = "Value from OnAdd";
}

private async Task OnGridCancel(GridCommandEventArgs args)
{
if (ShouldConfirmOnCancel && TelerikDialogs != null)
{
bool shouldContinue = await TelerikDialogs.ConfirmAsync("Do you want to discard your changes?");

if (!shouldContinue)
{
args.IsCancelled = true;
}
}
}

private async Task OnGridCreate(GridCommandEventArgs args)
{
var createdItem = (Product)args.Item;

// Create the item in the database.
int newId = await GridProductService.Create(createdItem);

// Reload the data from the database.
GridData = await GridProductService.Read();
// OR
// Create the item in the local data instead of reloading.
//createdItem.Id = newId;
//GridData.Insert(0, createdItem);
}

private async Task OnGridDelete(GridCommandEventArgs args)
{
var deletedItem = (Product)args.Item;

// Delete the item in the database.
await GridProductService.Delete(deletedItem);

// Reload the data from the database.
GridData = await GridProductService.Read();
// OR
// Delete the item in the local data instead of reloading.
//GridData.Remove(deletedItem);
}

private void OnGridEdit(GridCommandEventArgs args)
{
if (ShouldCancelOnAddEdit)
{
args.IsCancelled = true;
}
}

private Product OnGridModelInit()
{
return new Product() { Description = "Value from OnModelInit" };
}

private async Task OnGridUpdate(GridCommandEventArgs args)
{
var updatedItem = (Product)args.Item;

// Update the item in the database.
bool success = await GridProductService.Update(updatedItem);

// Reload the data from the database.
GridData = await GridProductService.Read();
// OR
// Update the item in the local data instead of reloading.
//int originalItemIndex = GridData.FindIndex(i => i.Id == updatedItem.Id);
//if (originalItemIndex != -1)
//{
// GridData[originalItemIndex] = updatedItem;
//}
}

#endregion Grid Events

protected override async Task OnInitializedAsync()
{
GridData = await GridProductService.Read();
}
#end
Loading