diff --git a/DbFirst.BlazorWasm/Components/CatalogsGrid.razor b/DbFirst.BlazorWasm/Components/CatalogsGrid.razor index 2453a44..3d9149f 100644 --- a/DbFirst.BlazorWasm/Components/CatalogsGrid.razor +++ b/DbFirst.BlazorWasm/Components/CatalogsGrid.razor @@ -1,3 +1,4 @@ +@using Microsoft.AspNetCore.Components.Forms @inject CatalogApiClient Api @if (!string.IsNullOrWhiteSpace(errorMessage)) @@ -55,41 +59,6 @@ else if (!string.IsNullOrWhiteSpace(infoMessage)) } -
- Neuen Eintrag anlegen -
- -@if (showForm) -{ -
- - - - - - - - - @if (isEditing) - { - - - - } - - - @((isEditing ? "Speichern" : "Anlegen")) - Abbrechen - - - - -
-} - @if (isLoading) {

Lade Daten...

@@ -101,68 +70,61 @@ else if (items.Count == 0) else {
- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @{ var item = (CatalogReadDto)cell.DataItem; } -
- Bearbeiten - Löschen -
-
-
+ + + + + + + +
+ + @{ SetEditContext(editFormContext.EditContext); var editModel = (CatalogEditModel)editFormContext.EditModel; } + + + + + + + + + + + + + + +
} @code { private List items = new(); - private CatalogWriteDto formModel = new(); - private int editingId; private bool isLoading; - private bool isEditing; - private bool showForm; private string? errorMessage; private string? infoMessage; + private EditContext? editContext; + private ValidationMessageStore? validationMessageStore; private readonly List procedureOptions = new() { @@ -175,6 +137,57 @@ else await LoadCatalogs(); } + private void SetEditContext(EditContext context) + { + if (editContext == context) + { + return; + } + + if (editContext != null) + { + editContext.OnFieldChanged -= OnEditFieldChanged; + } + + editContext = context; + validationMessageStore = new ValidationMessageStore(editContext); + editContext.OnFieldChanged += OnEditFieldChanged; + } + + private void OnEditFieldChanged(object? sender, FieldChangedEventArgs e) + { + if (validationMessageStore == null || editContext == null) + { + return; + } + + if (e.FieldIdentifier.FieldName == nameof(CatalogEditModel.UpdateProcedure) || + e.FieldIdentifier.FieldName == nameof(CatalogEditModel.CatTitle)) + { + validationMessageStore.Clear(); + editContext.NotifyValidationStateChanged(); + } + } + + private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e) + { + if (e.IsNew) + { + e.EditModel = new CatalogEditModel(); + return; + } + + var item = (CatalogReadDto)e.DataItem; + e.EditModel = new CatalogEditModel + { + Guid = item.Guid, + CatTitle = item.CatTitle, + CatString = item.CatString, + UpdateProcedure = 0, + OriginalCatTitle = item.CatTitle + }; + } + private async Task LoadCatalogs() { isLoading = true; @@ -194,88 +207,115 @@ else } } - private void StartCreate() + private async Task OnEditModelSaving(GridEditModelSavingEventArgs e) { - formModel = new CatalogWriteDto(); - editingId = 0; - isEditing = false; - showForm = true; - infoMessage = null; errorMessage = null; - } + infoMessage = null; - private void StartEdit(CatalogReadDto item) - { - formModel = new CatalogWriteDto + validationMessageStore?.Clear(); + editContext?.NotifyValidationStateChanged(); + + var editModel = (CatalogEditModel)e.EditModel; + if (!ValidateEditModel(editModel, e.IsNew)) { - CatTitle = item.CatTitle, - CatString = item.CatString, - UpdateProcedure = 0 - }; - editingId = item.Guid; - isEditing = true; - showForm = true; - infoMessage = null; - errorMessage = null; - } + e.Cancel = true; + return; + } - private async Task HandleSubmit() - { - errorMessage = null; - infoMessage = null; + var dto = new CatalogWriteDto + { + CatTitle = editModel.CatTitle, + CatString = editModel.CatString, + UpdateProcedure = editModel.UpdateProcedure + }; try { - if (isEditing) + if (e.IsNew) { - var updated = await Api.UpdateAsync(editingId, formModel); - if (!updated.Success) - { - errorMessage = updated.Error ?? "Aktualisierung fehlgeschlagen."; - return; - } - - infoMessage = "Katalog aktualisiert."; - } - else - { - var created = await Api.CreateAsync(formModel); + var created = await Api.CreateAsync(dto); if (!created.Success || created.Value == null) { - errorMessage = created.Error ?? "Anlegen fehlgeschlagen."; + if (!string.IsNullOrWhiteSpace(created.Error)) + { + AddValidationError(editModel, nameof(CatalogEditModel.CatTitle), created.Error); + } + else + { + errorMessage = "Anlegen fehlgeschlagen."; + } + + e.Cancel = true; return; } infoMessage = "Katalog angelegt."; } + else + { + var updated = await Api.UpdateAsync(editModel.Guid, dto); + if (!updated.Success) + { + errorMessage = updated.Error ?? "Aktualisierung fehlgeschlagen."; + e.Cancel = true; + return; + } + + infoMessage = "Katalog aktualisiert."; + } - showForm = false; await LoadCatalogs(); } catch (Exception ex) { errorMessage = $"Fehler beim Speichern: {ex.Message}"; + e.Cancel = true; } } - private void CancelEdit() + private void AddValidationError(CatalogEditModel editModel, string fieldName, string message) { - showForm = false; - infoMessage = null; - errorMessage = null; + if (editContext == null || validationMessageStore == null) + { + return; + } + + var field = new FieldIdentifier(editModel, fieldName); + validationMessageStore.Add(field, message); + editContext.NotifyValidationStateChanged(); } - private async Task DeleteCatalog(int id) + private bool ValidateEditModel(CatalogEditModel editModel, bool isNew) + { + if (isNew) + { + return true; + } + + if (editModel.UpdateProcedure == 0 && + !string.Equals(editModel.CatTitle, editModel.OriginalCatTitle, StringComparison.OrdinalIgnoreCase)) + { + AddValidationError(editModel, nameof(CatalogEditModel.CatTitle), "Titel kann nicht geändert werden."); + return false; + } + + return true; + } + + private async Task OnDataItemDeleting(GridDataItemDeletingEventArgs e) { errorMessage = null; infoMessage = null; + var item = (CatalogReadDto)e.DataItem; + try { - var deleted = await Api.DeleteAsync(id); + var deleted = await Api.DeleteAsync(item.Guid); if (!deleted.Success) { errorMessage = deleted.Error ?? "Löschen fehlgeschlagen."; + e.Cancel = true; return; } @@ -285,9 +325,19 @@ else catch (Exception ex) { errorMessage = $"Fehler beim Löschen: {ex.Message}"; + e.Cancel = true; } } + private sealed class CatalogEditModel + { + public int Guid { get; set; } + public string CatTitle { get; set; } = string.Empty; + public string CatString { get; set; } = string.Empty; + public int UpdateProcedure { get; set; } + public string OriginalCatTitle { get; set; } = string.Empty; + } + private sealed class ProcedureOption { public int Value { get; set; } diff --git a/DbFirst.BlazorWasm/Components/MassDataGrid.razor b/DbFirst.BlazorWasm/Components/MassDataGrid.razor index 6c7e100..b4f5524 100644 --- a/DbFirst.BlazorWasm/Components/MassDataGrid.razor +++ b/DbFirst.BlazorWasm/Components/MassDataGrid.razor @@ -61,38 +61,6 @@ else if (!string.IsNullOrWhiteSpace(infoMessage)) } -
- Neuen Eintrag anlegen -
- -@if (showForm) -{ -
- - - - - - - - - - - - - - - - - Speichern - Abbrechen - - - - -
-} - @if (isLoading) {

Lade Daten...

@@ -104,9 +72,21 @@ else if (items.Count == 0) else {
- + - + + - + - + - + - + - - - @{ var item = (MassDataReadDto)cell.DataItem; } -
- Bearbeiten - Löschen -
-
-
+ + + + @editFormContext.GetEditor(nameof(MassDataReadDto.CustomerName)) + + + @editFormContext.GetEditor(nameof(MassDataReadDto.Amount)) + + + @editFormContext.GetEditor(nameof(MassDataReadDto.Category)) + + + @editFormContext.GetEditor(nameof(MassDataReadDto.StatusFlag)) + + +
@@ -176,10 +163,7 @@ else @code { private const int PageSize = 100; private List items = new(); - private MassDataWriteDto formModel = new(); - private string amountText = string.Empty; private bool isLoading; - private bool showForm; private string? errorMessage; private string? infoMessage; private int pageIndex; @@ -219,61 +203,38 @@ else await LoadPage(index); } - private void StartCreate() + private async Task OnEditModelSaving(GridEditModelSavingEventArgs e) { - infoMessage = "Anlegen ist aktuell noch nicht verfügbar."; - } + errorMessage = null; + infoMessage = null; - private void StartEdit(MassDataReadDto item) - { - formModel = new MassDataWriteDto + var editModel = (MassDataReadDto)e.EditModel; + var dto = new MassDataWriteDto { - CustomerName = item.CustomerName, - Amount = item.Amount, - Category = item.Category, - StatusFlag = item.StatusFlag + CustomerName = editModel.CustomerName, + Amount = editModel.Amount, + Category = editModel.Category, + StatusFlag = editModel.StatusFlag }; - amountText = item.Amount.ToString("0.00"); - showForm = true; - infoMessage = null; - errorMessage = null; - } - - private async Task HandleSubmit() - { - errorMessage = null; - infoMessage = null; - - if (!decimal.TryParse(amountText, out var amount)) - { - errorMessage = "Amount ist ungültig."; - return; - } - - formModel.Amount = amount; try { - await Api.UpsertAsync(formModel); + await Api.UpsertAsync(dto); infoMessage = "MassData aktualisiert."; - showForm = false; await LoadPage(pageIndex); } catch (Exception ex) { errorMessage = $"Fehler beim Speichern: {ex.Message}"; + e.Cancel = true; } } - private void CancelEdit() + private Task OnDataItemDeleting(GridDataItemDeletingEventArgs e) { - showForm = false; - infoMessage = null; errorMessage = null; - } - - private void ShowDeleteNotReady() - { infoMessage = "Löschen ist aktuell noch nicht verfügbar."; + e.Cancel = true; + return Task.CompletedTask; } } diff --git a/DbFirst.BlazorWebApp/Components/CatalogsGrid.razor b/DbFirst.BlazorWebApp/Components/CatalogsGrid.razor index fd77d59..999a8cc 100644 --- a/DbFirst.BlazorWebApp/Components/CatalogsGrid.razor +++ b/DbFirst.BlazorWebApp/Components/CatalogsGrid.razor @@ -1,8 +1,12 @@ +@using Microsoft.AspNetCore.Components.Forms @inject CatalogApiClient Api @if (!string.IsNullOrWhiteSpace(errorMessage)) @@ -14,41 +18,6 @@ else if (!string.IsNullOrWhiteSpace(infoMessage)) } -
- Neuen Eintrag anlegen -
- -@if (showForm) -{ -
- - - - - - - - - @if (isEditing) - { - - - - } - - - @((isEditing ? "Speichern" : "Anlegen")) - Abbrechen - - - - -
-} - @if (isLoading) {

Lade Daten...

@@ -60,38 +29,61 @@ else if (items.Count == 0) else {
- + + - - - - - - - @{ var item = (CatalogReadDto)cell.DataItem; } -
- Bearbeiten - Löschen -
-
-
+ + + +
+ + @{ SetEditContext(editFormContext.EditContext); var editModel = (CatalogEditModel)editFormContext.EditModel; } + + + + + + + + + + + + + + +
} @code { private List items = new(); - private CatalogWriteDto formModel = new(); - private int editingId; private bool isLoading; - private bool isEditing; - private bool showForm; private string? errorMessage; private string? infoMessage; + private EditContext? editContext; + private ValidationMessageStore? validationMessageStore; private readonly List procedureOptions = new() { @@ -104,6 +96,57 @@ else await LoadCatalogs(); } + private void SetEditContext(EditContext context) + { + if (editContext == context) + { + return; + } + + if (editContext != null) + { + editContext.OnFieldChanged -= OnEditFieldChanged; + } + + editContext = context; + validationMessageStore = new ValidationMessageStore(editContext); + editContext.OnFieldChanged += OnEditFieldChanged; + } + + private void OnEditFieldChanged(object? sender, FieldChangedEventArgs e) + { + if (validationMessageStore == null || editContext == null) + { + return; + } + + if (e.FieldIdentifier.FieldName == nameof(CatalogEditModel.UpdateProcedure) || + e.FieldIdentifier.FieldName == nameof(CatalogEditModel.CatTitle)) + { + validationMessageStore.Clear(); + editContext.NotifyValidationStateChanged(); + } + } + + private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e) + { + if (e.IsNew) + { + e.EditModel = new CatalogEditModel(); + return; + } + + var item = (CatalogReadDto)e.DataItem; + e.EditModel = new CatalogEditModel + { + Guid = item.Guid, + CatTitle = item.CatTitle, + CatString = item.CatString, + UpdateProcedure = 0, + OriginalCatTitle = item.CatTitle + }; + } + private async Task LoadCatalogs() { isLoading = true; @@ -123,88 +166,115 @@ else } } - private void StartCreate() + private async Task OnEditModelSaving(GridEditModelSavingEventArgs e) { - formModel = new CatalogWriteDto(); - editingId = 0; - isEditing = false; - showForm = true; - infoMessage = null; errorMessage = null; - } + infoMessage = null; - private void StartEdit(CatalogReadDto item) - { - formModel = new CatalogWriteDto + validationMessageStore?.Clear(); + editContext?.NotifyValidationStateChanged(); + + var editModel = (CatalogEditModel)e.EditModel; + if (!ValidateEditModel(editModel, e.IsNew)) { - CatTitle = item.CatTitle, - CatString = item.CatString, - UpdateProcedure = 0 - }; - editingId = item.Guid; - isEditing = true; - showForm = true; - infoMessage = null; - errorMessage = null; - } + e.Cancel = true; + return; + } - private async Task HandleSubmit() - { - errorMessage = null; - infoMessage = null; + var dto = new CatalogWriteDto + { + CatTitle = editModel.CatTitle, + CatString = editModel.CatString, + UpdateProcedure = editModel.UpdateProcedure + }; try { - if (isEditing) + if (e.IsNew) { - var updated = await Api.UpdateAsync(editingId, formModel); - if (!updated.Success) - { - errorMessage = updated.Error ?? "Aktualisierung fehlgeschlagen."; - return; - } - - infoMessage = "Katalog aktualisiert."; - } - else - { - var created = await Api.CreateAsync(formModel); + var created = await Api.CreateAsync(dto); if (!created.Success || created.Value == null) { - errorMessage = created.Error ?? "Anlegen fehlgeschlagen."; + if (!string.IsNullOrWhiteSpace(created.Error)) + { + AddValidationError(editModel, nameof(CatalogEditModel.CatTitle), created.Error); + } + else + { + errorMessage = "Anlegen fehlgeschlagen."; + } + + e.Cancel = true; return; } infoMessage = "Katalog angelegt."; } + else + { + var updated = await Api.UpdateAsync(editModel.Guid, dto); + if (!updated.Success) + { + errorMessage = updated.Error ?? "Aktualisierung fehlgeschlagen."; + e.Cancel = true; + return; + } + + infoMessage = "Katalog aktualisiert."; + } - showForm = false; await LoadCatalogs(); } catch (Exception ex) { errorMessage = $"Fehler beim Speichern: {ex.Message}"; + e.Cancel = true; } } - private void CancelEdit() + private void AddValidationError(CatalogEditModel editModel, string fieldName, string message) { - showForm = false; - infoMessage = null; - errorMessage = null; + if (editContext == null || validationMessageStore == null) + { + return; + } + + var field = new FieldIdentifier(editModel, fieldName); + validationMessageStore.Add(field, message); + editContext.NotifyValidationStateChanged(); } - private async Task DeleteCatalog(int id) + private bool ValidateEditModel(CatalogEditModel editModel, bool isNew) + { + if (isNew) + { + return true; + } + + if (editModel.UpdateProcedure == 0 && + !string.Equals(editModel.CatTitle, editModel.OriginalCatTitle, StringComparison.OrdinalIgnoreCase)) + { + AddValidationError(editModel, nameof(CatalogEditModel.CatTitle), "Titel kann nicht geändert werden."); + return false; + } + + return true; + } + + private async Task OnDataItemDeleting(GridDataItemDeletingEventArgs e) { errorMessage = null; infoMessage = null; + var item = (CatalogReadDto)e.DataItem; + try { - var deleted = await Api.DeleteAsync(id); + var deleted = await Api.DeleteAsync(item.Guid); if (!deleted.Success) { errorMessage = deleted.Error ?? "Löschen fehlgeschlagen."; + e.Cancel = true; return; } @@ -214,9 +284,19 @@ else catch (Exception ex) { errorMessage = $"Fehler beim Löschen: {ex.Message}"; + e.Cancel = true; } } + private sealed class CatalogEditModel + { + public int Guid { get; set; } + public string CatTitle { get; set; } = string.Empty; + public string CatString { get; set; } = string.Empty; + public int UpdateProcedure { get; set; } + public string OriginalCatTitle { get; set; } = string.Empty; + } + private sealed class ProcedureOption { public int Value { get; set; } diff --git a/DbFirst.BlazorWebApp/Components/MassDataGrid.razor b/DbFirst.BlazorWebApp/Components/MassDataGrid.razor index 6c7e100..b4f5524 100644 --- a/DbFirst.BlazorWebApp/Components/MassDataGrid.razor +++ b/DbFirst.BlazorWebApp/Components/MassDataGrid.razor @@ -61,38 +61,6 @@ else if (!string.IsNullOrWhiteSpace(infoMessage)) } -
- Neuen Eintrag anlegen -
- -@if (showForm) -{ -
- - - - - - - - - - - - - - - - - Speichern - Abbrechen - - - - -
-} - @if (isLoading) {

Lade Daten...

@@ -104,9 +72,21 @@ else if (items.Count == 0) else {
- + - + + - + - + - + - + - - - @{ var item = (MassDataReadDto)cell.DataItem; } -
- Bearbeiten - Löschen -
-
-
+ + + + @editFormContext.GetEditor(nameof(MassDataReadDto.CustomerName)) + + + @editFormContext.GetEditor(nameof(MassDataReadDto.Amount)) + + + @editFormContext.GetEditor(nameof(MassDataReadDto.Category)) + + + @editFormContext.GetEditor(nameof(MassDataReadDto.StatusFlag)) + + +
@@ -176,10 +163,7 @@ else @code { private const int PageSize = 100; private List items = new(); - private MassDataWriteDto formModel = new(); - private string amountText = string.Empty; private bool isLoading; - private bool showForm; private string? errorMessage; private string? infoMessage; private int pageIndex; @@ -219,61 +203,38 @@ else await LoadPage(index); } - private void StartCreate() + private async Task OnEditModelSaving(GridEditModelSavingEventArgs e) { - infoMessage = "Anlegen ist aktuell noch nicht verfügbar."; - } + errorMessage = null; + infoMessage = null; - private void StartEdit(MassDataReadDto item) - { - formModel = new MassDataWriteDto + var editModel = (MassDataReadDto)e.EditModel; + var dto = new MassDataWriteDto { - CustomerName = item.CustomerName, - Amount = item.Amount, - Category = item.Category, - StatusFlag = item.StatusFlag + CustomerName = editModel.CustomerName, + Amount = editModel.Amount, + Category = editModel.Category, + StatusFlag = editModel.StatusFlag }; - amountText = item.Amount.ToString("0.00"); - showForm = true; - infoMessage = null; - errorMessage = null; - } - - private async Task HandleSubmit() - { - errorMessage = null; - infoMessage = null; - - if (!decimal.TryParse(amountText, out var amount)) - { - errorMessage = "Amount ist ungültig."; - return; - } - - formModel.Amount = amount; try { - await Api.UpsertAsync(formModel); + await Api.UpsertAsync(dto); infoMessage = "MassData aktualisiert."; - showForm = false; await LoadPage(pageIndex); } catch (Exception ex) { errorMessage = $"Fehler beim Speichern: {ex.Message}"; + e.Cancel = true; } } - private void CancelEdit() + private Task OnDataItemDeleting(GridDataItemDeletingEventArgs e) { - showForm = false; - infoMessage = null; errorMessage = null; - } - - private void ShowDeleteNotReady() - { infoMessage = "Löschen ist aktuell noch nicht verfügbar."; + e.Cancel = true; + return Task.CompletedTask; } }