Refactor MassDataGrid editing and validation logic
- Switch to custom edit model (MassDataEditModel) for popup editing, enabling granular field validation and UI control - Replace default editors with explicit DxTextBox/DxCheckBox bindings - Add AmountText field for string input and validation; validate and convert in OnEditModelSaving - Implement duplicate customer check via new GetByCustomerNameAsync API method - Show ValidationSummary in popup; manage validation state with ValidationMessageStore and EditContext - Make popup header and width dynamic; show procedure ComboBox only for existing records - Restore "New" button in grid command column - Refactor CatalogsGrid to handle validation clearing in OnEditFieldChanged instead of OnTitleChanged - General improvements to real-time validation feedback
This commit is contained in:
@@ -138,10 +138,7 @@ else
|
|||||||
@{ SetEditContext(editFormContext.EditContext); var editModel = (CatalogEditModel)editFormContext.EditModel; SetPopupHeaderText(editModel.IsNew); }
|
@{ SetEditContext(editFormContext.EditContext); var editModel = (CatalogEditModel)editFormContext.EditModel; SetPopupHeaderText(editModel.IsNew); }
|
||||||
<DxFormLayout ColCount="2">
|
<DxFormLayout ColCount="2">
|
||||||
<DxFormLayoutItem Caption="Titel">
|
<DxFormLayoutItem Caption="Titel">
|
||||||
<DxTextBox @bind-Text="editModel.CatTitle"
|
<DxTextBox @bind-Text="editModel.CatTitle" Width="100%" />
|
||||||
@bind-Text:after="OnTitleChanged"
|
|
||||||
BindValueMode="BindValueMode.OnInput"
|
|
||||||
Width="100%" />
|
|
||||||
</DxFormLayoutItem>
|
</DxFormLayoutItem>
|
||||||
<DxFormLayoutItem Caption="Kennung">
|
<DxFormLayoutItem Caption="Kennung">
|
||||||
<DxTextBox @bind-Text="editModel.CatString" Width="100%" />
|
<DxTextBox @bind-Text="editModel.CatString" Width="100%" />
|
||||||
@@ -215,19 +212,15 @@ else
|
|||||||
{
|
{
|
||||||
validationMessageStore.Clear();
|
validationMessageStore.Clear();
|
||||||
editContext.NotifyValidationStateChanged();
|
editContext.NotifyValidationStateChanged();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTitleChanged()
|
|
||||||
{
|
|
||||||
if (validationMessageStore == null || editContext == null)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var field = new FieldIdentifier(editContext.Model, nameof(CatalogEditModel.CatTitle));
|
if (e.FieldIdentifier.FieldName == nameof(CatalogEditModel.CatTitle))
|
||||||
validationMessageStore.Clear(field);
|
{
|
||||||
editContext.NotifyValidationStateChanged();
|
var field = new FieldIdentifier(editContext.Model, nameof(CatalogEditModel.CatTitle));
|
||||||
|
validationMessageStore.Clear(field);
|
||||||
|
editContext.NotifyValidationStateChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e)
|
private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@using Microsoft.AspNetCore.Components.Forms
|
||||||
@inject MassDataApiClient Api
|
@inject MassDataApiClient Api
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -50,6 +51,9 @@
|
|||||||
background-position: right 0.5rem center;
|
background-position: right 0.5rem center;
|
||||||
background-size: 0.9rem;
|
background-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
.massdata-edit-popup {
|
||||||
|
min-width: 720px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(errorMessage))
|
@if (!string.IsNullOrWhiteSpace(errorMessage))
|
||||||
@@ -82,11 +86,13 @@ else
|
|||||||
PageSize="100"
|
PageSize="100"
|
||||||
CssClass="mb-3 massdata-grid"
|
CssClass="mb-3 massdata-grid"
|
||||||
EditMode="GridEditMode.PopupEditForm"
|
EditMode="GridEditMode.PopupEditForm"
|
||||||
PopupEditFormHeaderText="Bearbeiten"
|
PopupEditFormCssClass="massdata-edit-popup"
|
||||||
|
PopupEditFormHeaderText="@popupHeaderText"
|
||||||
|
CustomizeEditModel="OnCustomizeEditModel"
|
||||||
EditModelSaving="OnEditModelSaving"
|
EditModelSaving="OnEditModelSaving"
|
||||||
DataItemDeleting="OnDataItemDeleting">
|
DataItemDeleting="OnDataItemDeleting">
|
||||||
<Columns>
|
<Columns>
|
||||||
<DxGridCommandColumn Width="120px" NewButtonVisible="false" />
|
<DxGridCommandColumn Width="120px" />
|
||||||
<DxGridDataColumn FieldName="@nameof(MassDataReadDto.Id)" Caption="Id" Width="90px" ReadOnly="true">
|
<DxGridDataColumn FieldName="@nameof(MassDataReadDto.Id)" Caption="Id" Width="90px" ReadOnly="true">
|
||||||
<FilterRowCellTemplate Context="filter">
|
<FilterRowCellTemplate Context="filter">
|
||||||
<DxTextBox Text="@(filter.FilterRowValue?.ToString())"
|
<DxTextBox Text="@(filter.FilterRowValue?.ToString())"
|
||||||
@@ -143,18 +149,34 @@ else
|
|||||||
</DxGridDataColumn>
|
</DxGridDataColumn>
|
||||||
</Columns>
|
</Columns>
|
||||||
<EditFormTemplate Context="editFormContext">
|
<EditFormTemplate Context="editFormContext">
|
||||||
<DxFormLayout>
|
@{ SetEditContext(editFormContext.EditContext); var editModel = (MassDataEditModel)editFormContext.EditModel; SetPopupHeaderText(editModel.IsNew); }
|
||||||
|
<DxFormLayout ColCount="2">
|
||||||
<DxFormLayoutItem Caption="CustomerName">
|
<DxFormLayoutItem Caption="CustomerName">
|
||||||
@editFormContext.GetEditor(nameof(MassDataReadDto.CustomerName))
|
<DxTextBox @bind-Text="editModel.CustomerName" Width="100%" />
|
||||||
</DxFormLayoutItem>
|
</DxFormLayoutItem>
|
||||||
<DxFormLayoutItem Caption="Amount">
|
<DxFormLayoutItem Caption="Amount">
|
||||||
@editFormContext.GetEditor(nameof(MassDataReadDto.Amount))
|
<DxTextBox @bind-Text="editModel.AmountText" Width="100%" />
|
||||||
</DxFormLayoutItem>
|
</DxFormLayoutItem>
|
||||||
<DxFormLayoutItem Caption="Category">
|
<DxFormLayoutItem Caption="Category">
|
||||||
@editFormContext.GetEditor(nameof(MassDataReadDto.Category))
|
<DxTextBox @bind-Text="editModel.Category" Width="100%" ReadOnly="@(!editModel.IsNew)" />
|
||||||
</DxFormLayoutItem>
|
</DxFormLayoutItem>
|
||||||
<DxFormLayoutItem Caption="Status">
|
<DxFormLayoutItem Caption="Status">
|
||||||
@editFormContext.GetEditor(nameof(MassDataReadDto.StatusFlag))
|
<DxCheckBox @bind-Checked="editModel.StatusFlag" ReadOnly="@(!editModel.IsNew)" />
|
||||||
|
</DxFormLayoutItem>
|
||||||
|
@if (!editModel.IsNew)
|
||||||
|
{
|
||||||
|
<DxFormLayoutItem Caption="Prozedur">
|
||||||
|
<DxComboBox Data="@procedureOptions"
|
||||||
|
TData="ProcedureOption"
|
||||||
|
TValue="int"
|
||||||
|
TextFieldName="Text"
|
||||||
|
ValueFieldName="Value"
|
||||||
|
@bind-Value="editModel.UpdateProcedure"
|
||||||
|
Width="100%" />
|
||||||
|
</DxFormLayoutItem>
|
||||||
|
}
|
||||||
|
<DxFormLayoutItem ColSpanMd="12">
|
||||||
|
<ValidationSummary />
|
||||||
</DxFormLayoutItem>
|
</DxFormLayoutItem>
|
||||||
</DxFormLayout>
|
</DxFormLayout>
|
||||||
</EditFormTemplate>
|
</EditFormTemplate>
|
||||||
@@ -174,6 +196,9 @@ else
|
|||||||
private string? infoMessage;
|
private string? infoMessage;
|
||||||
private int pageIndex;
|
private int pageIndex;
|
||||||
private int pageCount = 1;
|
private int pageCount = 1;
|
||||||
|
private string popupHeaderText = "Edit";
|
||||||
|
private EditContext? editContext;
|
||||||
|
private ValidationMessageStore? validationMessageStore;
|
||||||
|
|
||||||
private readonly List<BoolFilterOption> statusFilterOptions = new()
|
private readonly List<BoolFilterOption> statusFilterOptions = new()
|
||||||
{
|
{
|
||||||
@@ -182,6 +207,11 @@ else
|
|||||||
new() { Value = false, Text = "False" }
|
new() { Value = false, Text = "False" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private readonly List<ProcedureOption> procedureOptions = new()
|
||||||
|
{
|
||||||
|
new() { Value = 0, Text = "PRMassdata_UpsertByCustomerName" }
|
||||||
|
};
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
await LoadPage(0);
|
await LoadPage(0);
|
||||||
@@ -216,16 +246,105 @@ else
|
|||||||
await LoadPage(index);
|
await LoadPage(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(MassDataEditModel.UpdateProcedure))
|
||||||
|
{
|
||||||
|
validationMessageStore.Clear();
|
||||||
|
editContext.NotifyValidationStateChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.FieldIdentifier.FieldName == nameof(MassDataEditModel.CustomerName))
|
||||||
|
{
|
||||||
|
var field = new FieldIdentifier(editContext.Model, nameof(MassDataEditModel.CustomerName));
|
||||||
|
validationMessageStore.Clear(field);
|
||||||
|
editContext.NotifyValidationStateChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetPopupHeaderText(bool isNew)
|
||||||
|
{
|
||||||
|
popupHeaderText = isNew ? "Neu" : "Edit";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.IsNew)
|
||||||
|
{
|
||||||
|
e.EditModel = new MassDataEditModel { IsNew = true, UpdateProcedure = procedureOptions[0].Value };
|
||||||
|
SetPopupHeaderText(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var item = (MassDataReadDto)e.DataItem;
|
||||||
|
e.EditModel = new MassDataEditModel
|
||||||
|
{
|
||||||
|
Id = item.Id,
|
||||||
|
CustomerName = item.CustomerName,
|
||||||
|
AmountText = item.Amount.ToString("0.00"),
|
||||||
|
Category = item.Category,
|
||||||
|
StatusFlag = item.StatusFlag,
|
||||||
|
UpdateProcedure = procedureOptions[0].Value,
|
||||||
|
IsNew = false,
|
||||||
|
OriginalCustomerName = item.CustomerName
|
||||||
|
};
|
||||||
|
SetPopupHeaderText(false);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task OnEditModelSaving(GridEditModelSavingEventArgs e)
|
private async Task OnEditModelSaving(GridEditModelSavingEventArgs e)
|
||||||
{
|
{
|
||||||
errorMessage = null;
|
errorMessage = null;
|
||||||
infoMessage = null;
|
infoMessage = null;
|
||||||
|
|
||||||
var editModel = (MassDataReadDto)e.EditModel;
|
validationMessageStore?.Clear();
|
||||||
|
editContext?.NotifyValidationStateChanged();
|
||||||
|
|
||||||
|
var editModel = (MassDataEditModel)e.EditModel;
|
||||||
|
if (!decimal.TryParse(editModel.AmountText, out var amount))
|
||||||
|
{
|
||||||
|
AddValidationError(editModel, nameof(MassDataEditModel.AmountText), "Amount ist ungültig.");
|
||||||
|
e.Cancel = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editModel.IsNew)
|
||||||
|
{
|
||||||
|
var existing = await Api.GetByCustomerNameAsync(editModel.CustomerName);
|
||||||
|
if (existing != null)
|
||||||
|
{
|
||||||
|
AddValidationError(editModel, nameof(MassDataEditModel.CustomerName), "Kunde existiert bereits.");
|
||||||
|
e.Cancel = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var dto = new MassDataWriteDto
|
var dto = new MassDataWriteDto
|
||||||
{
|
{
|
||||||
CustomerName = editModel.CustomerName,
|
CustomerName = editModel.CustomerName,
|
||||||
Amount = editModel.Amount,
|
Amount = amount,
|
||||||
Category = editModel.Category,
|
Category = editModel.Category,
|
||||||
StatusFlag = editModel.StatusFlag
|
StatusFlag = editModel.StatusFlag
|
||||||
};
|
};
|
||||||
@@ -233,7 +352,7 @@ else
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Api.UpsertAsync(dto);
|
await Api.UpsertAsync(dto);
|
||||||
infoMessage = "MassData aktualisiert.";
|
infoMessage = editModel.IsNew ? "MassData angelegt." : "MassData aktualisiert.";
|
||||||
await LoadPage(pageIndex);
|
await LoadPage(pageIndex);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -243,6 +362,18 @@ else
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddValidationError(MassDataEditModel editModel, string fieldName, string message)
|
||||||
|
{
|
||||||
|
if (editContext == null || validationMessageStore == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var field = new FieldIdentifier(editModel, fieldName);
|
||||||
|
validationMessageStore.Add(field, message);
|
||||||
|
editContext.NotifyValidationStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
private Task OnDataItemDeleting(GridDataItemDeletingEventArgs e)
|
private Task OnDataItemDeleting(GridDataItemDeletingEventArgs e)
|
||||||
{
|
{
|
||||||
errorMessage = null;
|
errorMessage = null;
|
||||||
@@ -251,6 +382,24 @@ else
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sealed class MassDataEditModel
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string CustomerName { get; set; } = string.Empty;
|
||||||
|
public string AmountText { get; set; } = string.Empty;
|
||||||
|
public string Category { get; set; } = string.Empty;
|
||||||
|
public bool StatusFlag { get; set; }
|
||||||
|
public int UpdateProcedure { get; set; }
|
||||||
|
public bool IsNew { get; set; }
|
||||||
|
public string OriginalCustomerName { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class ProcedureOption
|
||||||
|
{
|
||||||
|
public int Value { get; set; }
|
||||||
|
public string Text { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
private sealed class BoolFilterOption
|
private sealed class BoolFilterOption
|
||||||
{
|
{
|
||||||
public bool? Value { get; set; }
|
public bool? Value { get; set; }
|
||||||
|
|||||||
@@ -32,4 +32,21 @@ public class MassDataApiClient
|
|||||||
var payload = await response.Content.ReadFromJsonAsync<MassDataReadDto>();
|
var payload = await response.Content.ReadFromJsonAsync<MassDataReadDto>();
|
||||||
return payload ?? new MassDataReadDto();
|
return payload ?? new MassDataReadDto();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<MassDataReadDto?> GetByCustomerNameAsync(string customerName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(customerName))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = await _httpClient.GetAsync($"{Endpoint}/{Uri.EscapeDataString(customerName)}");
|
||||||
|
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
return await response.Content.ReadFromJsonAsync<MassDataReadDto>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,10 +97,7 @@ else
|
|||||||
@{ SetEditContext(editFormContext.EditContext); var editModel = (CatalogEditModel)editFormContext.EditModel; SetPopupHeaderText(editModel.IsNew); }
|
@{ SetEditContext(editFormContext.EditContext); var editModel = (CatalogEditModel)editFormContext.EditModel; SetPopupHeaderText(editModel.IsNew); }
|
||||||
<DxFormLayout ColCount="2">
|
<DxFormLayout ColCount="2">
|
||||||
<DxFormLayoutItem Caption="Titel">
|
<DxFormLayoutItem Caption="Titel">
|
||||||
<DxTextBox @bind-Text="editModel.CatTitle"
|
<DxTextBox @bind-Text="editModel.CatTitle" Width="100%" />
|
||||||
@bind-Text:after="OnTitleChanged"
|
|
||||||
BindValueMode="BindValueMode.OnInput"
|
|
||||||
Width="100%" />
|
|
||||||
</DxFormLayoutItem>
|
</DxFormLayoutItem>
|
||||||
<DxFormLayoutItem Caption="Kennung">
|
<DxFormLayoutItem Caption="Kennung">
|
||||||
<DxTextBox @bind-Text="editModel.CatString" Width="100%" />
|
<DxTextBox @bind-Text="editModel.CatString" Width="100%" />
|
||||||
@@ -174,19 +171,15 @@ else
|
|||||||
{
|
{
|
||||||
validationMessageStore.Clear();
|
validationMessageStore.Clear();
|
||||||
editContext.NotifyValidationStateChanged();
|
editContext.NotifyValidationStateChanged();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTitleChanged()
|
|
||||||
{
|
|
||||||
if (validationMessageStore == null || editContext == null)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var field = new FieldIdentifier(editContext.Model, nameof(CatalogEditModel.CatTitle));
|
if (e.FieldIdentifier.FieldName == nameof(CatalogEditModel.CatTitle))
|
||||||
validationMessageStore.Clear(field);
|
{
|
||||||
editContext.NotifyValidationStateChanged();
|
var field = new FieldIdentifier(editContext.Model, nameof(CatalogEditModel.CatTitle));
|
||||||
|
validationMessageStore.Clear(field);
|
||||||
|
editContext.NotifyValidationStateChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetPopupHeaderText(bool isNew)
|
private void SetPopupHeaderText(bool isNew)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@using Microsoft.AspNetCore.Components.Forms
|
||||||
@inject MassDataApiClient Api
|
@inject MassDataApiClient Api
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -50,6 +51,9 @@
|
|||||||
background-position: right 0.5rem center;
|
background-position: right 0.5rem center;
|
||||||
background-size: 0.9rem;
|
background-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
.massdata-edit-popup {
|
||||||
|
min-width: 720px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(errorMessage))
|
@if (!string.IsNullOrWhiteSpace(errorMessage))
|
||||||
@@ -82,11 +86,13 @@ else
|
|||||||
PageSize="100"
|
PageSize="100"
|
||||||
CssClass="mb-3 massdata-grid"
|
CssClass="mb-3 massdata-grid"
|
||||||
EditMode="GridEditMode.PopupEditForm"
|
EditMode="GridEditMode.PopupEditForm"
|
||||||
PopupEditFormHeaderText="Bearbeiten"
|
PopupEditFormCssClass="massdata-edit-popup"
|
||||||
|
PopupEditFormHeaderText="@popupHeaderText"
|
||||||
|
CustomizeEditModel="OnCustomizeEditModel"
|
||||||
EditModelSaving="OnEditModelSaving"
|
EditModelSaving="OnEditModelSaving"
|
||||||
DataItemDeleting="OnDataItemDeleting">
|
DataItemDeleting="OnDataItemDeleting">
|
||||||
<Columns>
|
<Columns>
|
||||||
<DxGridCommandColumn Width="120px" NewButtonVisible="false" />
|
<DxGridCommandColumn Width="120px" />
|
||||||
<DxGridDataColumn FieldName="@nameof(MassDataReadDto.Id)" Caption="Id" Width="90px" ReadOnly="true">
|
<DxGridDataColumn FieldName="@nameof(MassDataReadDto.Id)" Caption="Id" Width="90px" ReadOnly="true">
|
||||||
<FilterRowCellTemplate Context="filter">
|
<FilterRowCellTemplate Context="filter">
|
||||||
<DxTextBox Text="@(filter.FilterRowValue?.ToString())"
|
<DxTextBox Text="@(filter.FilterRowValue?.ToString())"
|
||||||
@@ -143,18 +149,34 @@ else
|
|||||||
</DxGridDataColumn>
|
</DxGridDataColumn>
|
||||||
</Columns>
|
</Columns>
|
||||||
<EditFormTemplate Context="editFormContext">
|
<EditFormTemplate Context="editFormContext">
|
||||||
<DxFormLayout>
|
@{ SetEditContext(editFormContext.EditContext); var editModel = (MassDataEditModel)editFormContext.EditModel; SetPopupHeaderText(editModel.IsNew); }
|
||||||
|
<DxFormLayout ColCount="2">
|
||||||
<DxFormLayoutItem Caption="CustomerName">
|
<DxFormLayoutItem Caption="CustomerName">
|
||||||
@editFormContext.GetEditor(nameof(MassDataReadDto.CustomerName))
|
<DxTextBox @bind-Text="editModel.CustomerName" Width="100%" />
|
||||||
</DxFormLayoutItem>
|
</DxFormLayoutItem>
|
||||||
<DxFormLayoutItem Caption="Amount">
|
<DxFormLayoutItem Caption="Amount">
|
||||||
@editFormContext.GetEditor(nameof(MassDataReadDto.Amount))
|
<DxTextBox @bind-Text="editModel.AmountText" Width="100%" />
|
||||||
</DxFormLayoutItem>
|
</DxFormLayoutItem>
|
||||||
<DxFormLayoutItem Caption="Category">
|
<DxFormLayoutItem Caption="Category">
|
||||||
@editFormContext.GetEditor(nameof(MassDataReadDto.Category))
|
<DxTextBox @bind-Text="editModel.Category" Width="100%" ReadOnly="@(!editModel.IsNew)" />
|
||||||
</DxFormLayoutItem>
|
</DxFormLayoutItem>
|
||||||
<DxFormLayoutItem Caption="Status">
|
<DxFormLayoutItem Caption="Status">
|
||||||
@editFormContext.GetEditor(nameof(MassDataReadDto.StatusFlag))
|
<DxCheckBox @bind-Checked="editModel.StatusFlag" ReadOnly="@(!editModel.IsNew)" />
|
||||||
|
</DxFormLayoutItem>
|
||||||
|
@if (!editModel.IsNew)
|
||||||
|
{
|
||||||
|
<DxFormLayoutItem Caption="Prozedur">
|
||||||
|
<DxComboBox Data="@procedureOptions"
|
||||||
|
TData="ProcedureOption"
|
||||||
|
TValue="int"
|
||||||
|
TextFieldName="Text"
|
||||||
|
ValueFieldName="Value"
|
||||||
|
@bind-Value="editModel.UpdateProcedure"
|
||||||
|
Width="100%" />
|
||||||
|
</DxFormLayoutItem>
|
||||||
|
}
|
||||||
|
<DxFormLayoutItem ColSpanMd="12">
|
||||||
|
<ValidationSummary />
|
||||||
</DxFormLayoutItem>
|
</DxFormLayoutItem>
|
||||||
</DxFormLayout>
|
</DxFormLayout>
|
||||||
</EditFormTemplate>
|
</EditFormTemplate>
|
||||||
@@ -174,6 +196,9 @@ else
|
|||||||
private string? infoMessage;
|
private string? infoMessage;
|
||||||
private int pageIndex;
|
private int pageIndex;
|
||||||
private int pageCount = 1;
|
private int pageCount = 1;
|
||||||
|
private string popupHeaderText = "Edit";
|
||||||
|
private EditContext? editContext;
|
||||||
|
private ValidationMessageStore? validationMessageStore;
|
||||||
|
|
||||||
private readonly List<BoolFilterOption> statusFilterOptions = new()
|
private readonly List<BoolFilterOption> statusFilterOptions = new()
|
||||||
{
|
{
|
||||||
@@ -182,6 +207,11 @@ else
|
|||||||
new() { Value = false, Text = "False" }
|
new() { Value = false, Text = "False" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private readonly List<ProcedureOption> procedureOptions = new()
|
||||||
|
{
|
||||||
|
new() { Value = 0, Text = "PRMassdata_UpsertByCustomerName" }
|
||||||
|
};
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
await LoadPage(0);
|
await LoadPage(0);
|
||||||
@@ -216,16 +246,105 @@ else
|
|||||||
await LoadPage(index);
|
await LoadPage(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(MassDataEditModel.UpdateProcedure))
|
||||||
|
{
|
||||||
|
validationMessageStore.Clear();
|
||||||
|
editContext.NotifyValidationStateChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.FieldIdentifier.FieldName == nameof(MassDataEditModel.CustomerName))
|
||||||
|
{
|
||||||
|
var field = new FieldIdentifier(editContext.Model, nameof(MassDataEditModel.CustomerName));
|
||||||
|
validationMessageStore.Clear(field);
|
||||||
|
editContext.NotifyValidationStateChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetPopupHeaderText(bool isNew)
|
||||||
|
{
|
||||||
|
popupHeaderText = isNew ? "Neu" : "Edit";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.IsNew)
|
||||||
|
{
|
||||||
|
e.EditModel = new MassDataEditModel { IsNew = true, UpdateProcedure = procedureOptions[0].Value };
|
||||||
|
SetPopupHeaderText(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var item = (MassDataReadDto)e.DataItem;
|
||||||
|
e.EditModel = new MassDataEditModel
|
||||||
|
{
|
||||||
|
Id = item.Id,
|
||||||
|
CustomerName = item.CustomerName,
|
||||||
|
AmountText = item.Amount.ToString("0.00"),
|
||||||
|
Category = item.Category,
|
||||||
|
StatusFlag = item.StatusFlag,
|
||||||
|
UpdateProcedure = procedureOptions[0].Value,
|
||||||
|
IsNew = false,
|
||||||
|
OriginalCustomerName = item.CustomerName
|
||||||
|
};
|
||||||
|
SetPopupHeaderText(false);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task OnEditModelSaving(GridEditModelSavingEventArgs e)
|
private async Task OnEditModelSaving(GridEditModelSavingEventArgs e)
|
||||||
{
|
{
|
||||||
errorMessage = null;
|
errorMessage = null;
|
||||||
infoMessage = null;
|
infoMessage = null;
|
||||||
|
|
||||||
var editModel = (MassDataReadDto)e.EditModel;
|
validationMessageStore?.Clear();
|
||||||
|
editContext?.NotifyValidationStateChanged();
|
||||||
|
|
||||||
|
var editModel = (MassDataEditModel)e.EditModel;
|
||||||
|
if (!decimal.TryParse(editModel.AmountText, out var amount))
|
||||||
|
{
|
||||||
|
AddValidationError(editModel, nameof(MassDataEditModel.AmountText), "Amount ist ungültig.");
|
||||||
|
e.Cancel = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editModel.IsNew)
|
||||||
|
{
|
||||||
|
var existing = await Api.GetByCustomerNameAsync(editModel.CustomerName);
|
||||||
|
if (existing != null)
|
||||||
|
{
|
||||||
|
AddValidationError(editModel, nameof(MassDataEditModel.CustomerName), "Kunde existiert bereits.");
|
||||||
|
e.Cancel = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var dto = new MassDataWriteDto
|
var dto = new MassDataWriteDto
|
||||||
{
|
{
|
||||||
CustomerName = editModel.CustomerName,
|
CustomerName = editModel.CustomerName,
|
||||||
Amount = editModel.Amount,
|
Amount = amount,
|
||||||
Category = editModel.Category,
|
Category = editModel.Category,
|
||||||
StatusFlag = editModel.StatusFlag
|
StatusFlag = editModel.StatusFlag
|
||||||
};
|
};
|
||||||
@@ -233,7 +352,7 @@ else
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Api.UpsertAsync(dto);
|
await Api.UpsertAsync(dto);
|
||||||
infoMessage = "MassData aktualisiert.";
|
infoMessage = editModel.IsNew ? "MassData angelegt." : "MassData aktualisiert.";
|
||||||
await LoadPage(pageIndex);
|
await LoadPage(pageIndex);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -243,6 +362,18 @@ else
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddValidationError(MassDataEditModel editModel, string fieldName, string message)
|
||||||
|
{
|
||||||
|
if (editContext == null || validationMessageStore == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var field = new FieldIdentifier(editModel, fieldName);
|
||||||
|
validationMessageStore.Add(field, message);
|
||||||
|
editContext.NotifyValidationStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
private Task OnDataItemDeleting(GridDataItemDeletingEventArgs e)
|
private Task OnDataItemDeleting(GridDataItemDeletingEventArgs e)
|
||||||
{
|
{
|
||||||
errorMessage = null;
|
errorMessage = null;
|
||||||
@@ -251,6 +382,24 @@ else
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sealed class MassDataEditModel
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string CustomerName { get; set; } = string.Empty;
|
||||||
|
public string AmountText { get; set; } = string.Empty;
|
||||||
|
public string Category { get; set; } = string.Empty;
|
||||||
|
public bool StatusFlag { get; set; }
|
||||||
|
public int UpdateProcedure { get; set; }
|
||||||
|
public bool IsNew { get; set; }
|
||||||
|
public string OriginalCustomerName { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class ProcedureOption
|
||||||
|
{
|
||||||
|
public int Value { get; set; }
|
||||||
|
public string Text { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
private sealed class BoolFilterOption
|
private sealed class BoolFilterOption
|
||||||
{
|
{
|
||||||
public bool? Value { get; set; }
|
public bool? Value { get; set; }
|
||||||
|
|||||||
@@ -32,4 +32,21 @@ public class MassDataApiClient
|
|||||||
var payload = await response.Content.ReadFromJsonAsync<MassDataReadDto>();
|
var payload = await response.Content.ReadFromJsonAsync<MassDataReadDto>();
|
||||||
return payload ?? new MassDataReadDto();
|
return payload ?? new MassDataReadDto();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<MassDataReadDto?> GetByCustomerNameAsync(string customerName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(customerName))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = await _httpClient.GetAsync($"{Endpoint}/{Uri.EscapeDataString(customerName)}");
|
||||||
|
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
return await response.Content.ReadFromJsonAsync<MassDataReadDto>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user