InfoPanel: custom edit templates & null edit model fix

- Add InfoPanelEditTemplate to MgGridDataColumn for custom InfoPanel editors with refresh support
- Introduce MgGridInfoPanelEditContext for edit context/refresh
- Harden OnCustomizeEditModel to handle null edit models, preventing InfoPanel crashes and logging warnings
- Update docs: usage, editor resolution order, and new issue entry (ACBLAZOR-GRID-I-N7K2)
- Refactor grid templates to use new features and ensure consistent editor behavior
- Minor doc and formatting improvements
This commit is contained in:
Loretta 2026-07-12 08:36:20 +02:00
parent e72f5c1cb3
commit d63310b4d9
2 changed files with 54 additions and 45 deletions

View File

@ -30,7 +30,7 @@
<DxGridDataColumn FieldName="StockQuantity" />
<DxGridDataColumn FieldName="IncomingQuantity" ReadOnly="true" />
<DxGridDataColumn FieldName="NetWeight" ReadOnly="true" />
<DxGridDataColumn FieldName="IsMeasurable" />
<DxGridDataColumn FieldName="IsMeasurable" ReadOnly="true" />
<DxGridDataColumn FieldName="Tare" Caption="Tára súly" ReadOnly="true" />
<DxGridDataColumn FieldName="AverageWeight" ReadOnly="true" />
<DxGridDataColumn FieldName="AverageWeightTreshold" ReadOnly="true" />
@ -76,7 +76,8 @@
<ToolbarTemplate>
@if (IsMasterGrid)
{
<MgGridToolbarTemplate Grid="Grid" OnReloadDataClick="() => ReloadDataFromDb(true)" />
@* Termék-létrehozás/szerkesztés a nopadmin felületén történik — ez a grid csak listáz (nincs Add/Update SignalR tag) *@
<MgGridToolbarTemplate Grid="Grid" EnableNew="false" EnableEdit="false" OnReloadDataClick="() => ReloadDataFromDb(true)" />
}
</ToolbarTemplate>
</GridProductDto>

View File

@ -25,7 +25,7 @@
ParentDataItem="@ParentDataItem" Logger="_logger" ValidationEnabled="false" EditMode="GridEditMode.EditRow" OnGridFocusedRowChanged="Grid_FocusedRowChanged">
<Columns>
<MgGridDataColumn FieldName="Id" SortIndex="0" SortOrder="GridColumnSortOrder.Descending" ReadOnly="true"/>
<DxGridDataColumn FieldName="PartnerId" Caption="Partner" Visible="@(!ParentDataItemIsPartner)" ReadOnly="@ParentDataItemIsPartner">
<MgGridDataColumn FieldName="PartnerId" Caption="Partner" TextAlignment="GridTextAlignment.Left" Visible="@(!ParentDataItemIsPartner)" ReadOnly="@ParentDataItemIsPartner">
<CellDisplayTemplate>
@{
var sdPd = (ShippingDocument)context.DataItem;
@ -33,57 +33,28 @@
}
</CellDisplayTemplate>
<CellEditTemplate>
@{
var sdPe = (ShippingDocument)context.EditModel;
}
<DxComboBox TData="Partner" TValue="int"
Data="@Partners"
Value="@sdPe.PartnerId"
ValueChanged="@((int v) => OnPartnerChanged(sdPe, v))"
ValueExpression="@(() => sdPe.PartnerId)"
ValueFieldName="@nameof(Partner.Id)"
TextFieldName="@nameof(Partner.Name)"
DropDownBodyCssClass="dd-body-class"
ListRenderMode="ListRenderMode.Entire"
SearchMode="ListSearchMode.AutoSearch"
SearchFilterCondition="ListSearchFilterCondition.Contains"
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto">
<Columns>
<DxListEditorColumn FieldName="@nameof(Partner.Id)" />
<DxListEditorColumn FieldName="@nameof(Partner.Name)" />
<DxListEditorColumn FieldName="@nameof(Partner.TaxId)" />
</Columns>
</DxComboBox>
@PartnerEditor((ShippingDocument)context.EditModel)
</CellEditTemplate>
</DxGridDataColumn>
<DxGridDataColumn FieldName="PartnerDepotId" Caption="Telephely">
<InfoPanelEditTemplate>
@PartnerEditor((ShippingDocument)context.EditModel, context.Refresh)
</InfoPanelEditTemplate>
</MgGridDataColumn>
<MgGridDataColumn FieldName="PartnerDepotId" Caption="Telephely" TextAlignment="GridTextAlignment.Left">
<CellDisplayTemplate>
@{
var sdD = (ShippingDocument)context.DataItem;
var depotD = PartnersDictById.GetValueOrDefault(sdD.PartnerId)?.PartnerDepots?.FirstOrDefault(d => d.Id == sdD.PartnerDepotId);
<div style="text-align:left">@depotD?.Name</div>
<text>@depotD?.Name</text>
}
</CellDisplayTemplate>
<CellEditTemplate>
@{
var sdE = (ShippingDocument)context.EditModel;
var depotsE = PartnersDictById.GetValueOrDefault(sdE.PartnerId)?.PartnerDepots ?? new List<PartnerDepot>();
}
<DxComboBox TData="PartnerDepot" TValue="int?"
Data="@depotsE"
@bind-Value="sdE.PartnerDepotId"
ValueFieldName="@nameof(PartnerDepot.Id)"
TextFieldName="@nameof(PartnerDepot.Name)"
NullText="(telephely…)"
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto">
<Columns>
<DxListEditorColumn FieldName="@nameof(PartnerDepot.Name)" Caption="Név" />
<DxListEditorColumn FieldName="@nameof(PartnerDepot.FullAddress)" Caption="Cím" />
</Columns>
</DxComboBox>
@DepotEditor((ShippingDocument)context.EditModel)
</CellEditTemplate>
</DxGridDataColumn>
<InfoPanelEditTemplate>
@DepotEditor((ShippingDocument)context.EditModel)
</InfoPanelEditTemplate>
</MgGridDataColumn>
<DxGridDataColumn FieldName="Shipping.ShippingDate" Caption="Beérkezés" ReadOnly="true" />
<DxGridDataColumn FieldName="ShippingId" Caption="Shipping" Visible="@(!ParentDataItemIsShipping)" ReadOnly="@ParentDataItemIsShipping">
<EditSettings>
@ -327,6 +298,43 @@
StateHasChanged();
}
// Közös Partner/Telephely editorok: a grid-cella (CellEditTemplate) és az InfoPanel (InfoPanelEditTemplate)
// ugyanazt a combobox-ot kapja. A refresh a panel újrarenderelése (kaszkád: partner-váltás után frissüljön
// a Telephely-combo listája) — a grid-cellás útnál nem kell, ott a grid maga újrarenderel.
private RenderFragment PartnerEditor(ShippingDocument sd, Action? refresh = null) =>
@<DxComboBox TData="Partner" TValue="int"
Data="@Partners"
Value="@sd.PartnerId"
ValueChanged="@((int v) => { OnPartnerChanged(sd, v); refresh?.Invoke(); })"
ValueExpression="@(() => sd.PartnerId)"
ValueFieldName="@nameof(Partner.Id)"
TextFieldName="@nameof(Partner.Name)"
DropDownBodyCssClass="dd-body-class"
ListRenderMode="ListRenderMode.Entire"
SearchMode="ListSearchMode.AutoSearch"
SearchFilterCondition="ListSearchFilterCondition.Contains"
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto">
<Columns>
<DxListEditorColumn FieldName="@nameof(Partner.Id)" />
<DxListEditorColumn FieldName="@nameof(Partner.Name)" />
<DxListEditorColumn FieldName="@nameof(Partner.TaxId)" />
</Columns>
</DxComboBox>;
private RenderFragment DepotEditor(ShippingDocument sd) =>
@<DxComboBox TData="PartnerDepot" TValue="int?"
Data="@(PartnersDictById.GetValueOrDefault(sd.PartnerId)?.PartnerDepots ?? new List<PartnerDepot>())"
@bind-Value="sd.PartnerDepotId"
ValueFieldName="@nameof(PartnerDepot.Id)"
TextFieldName="@nameof(PartnerDepot.Name)"
NullText="(telephely…)"
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto">
<Columns>
<DxListEditorColumn FieldName="@nameof(PartnerDepot.Name)" Caption="Név" />
<DxListEditorColumn FieldName="@nameof(PartnerDepot.FullAddress)" Caption="Cím" />
</Columns>
</DxComboBox>;
protected async Task OnActiveTabChanged(int activeTabIndex)
{
_activeTabIndex = activeTabIndex;