diff --git a/AyCode.Blazor.Components/Components/CardViews/MgCardView.razor b/AyCode.Blazor.Components/Components/CardViews/MgCardView.razor
index ad2de7e..b1c4d9a 100644
--- a/AyCode.Blazor.Components/Components/CardViews/MgCardView.razor
+++ b/AyCode.Blazor.Components/Components/CardViews/MgCardView.razor
@@ -1,31 +1,36 @@
@typeparam TItem
-@if (ShowFilterPanel && FilterPanel is not null)
-{
-
- @FilterPanel
-
-}
-
-@if (Data is { Count: > 0 })
-{
-
- @foreach (var item in PagedItems)
- {
-
OnCardClickInternal(item)"
- style="@(OnCardClick.HasDelegate ? "cursor: pointer;" : "")">
- @CardTemplate(item)
-
- }
-
-
- @if (ShowPager && Data.Count > PageSize)
+
+ @if (ShowFilterPanel && FilterPanel is not null)
{
-
+
+ @FilterPanel
+
}
-}
+
+ @if (Data is { Count: > 0 })
+ {
+
+
+ @if (ShowPager && Data.Count > PageSize)
+ {
+
+ }
+ }
+
diff --git a/AyCode.Blazor.Components/Components/CardViews/MgCardView.razor.cs b/AyCode.Blazor.Components/Components/CardViews/MgCardView.razor.cs
index 9da93bf..e3e9133 100644
--- a/AyCode.Blazor.Components/Components/CardViews/MgCardView.razor.cs
+++ b/AyCode.Blazor.Components/Components/CardViews/MgCardView.razor.cs
@@ -1,15 +1,17 @@
using Microsoft.AspNetCore.Components;
+using Microsoft.JSInterop;
namespace AyCode.Blazor.Components.Components.CardViews;
///
-/// Generic card view component that displays items in a responsive grid layout.
-/// Uses DxGridLayout + DxLayoutBreakpoint for responsive column management
-/// and DxPager for optional pagination.
+/// Generic card view component that displays items in a responsive CSS Grid layout
+/// with optional pagination and scroll-to-item support.
///
/// The type of data item displayed in each card.
public partial class MgCardView : ComponentBase
{
+ [Inject] private IJSRuntime JSRuntime { get; set; } = null!;
+
///
/// The collection of items to display as cards.
///
@@ -70,6 +72,12 @@ public partial class MgCardView : ComponentBase
[Parameter]
public string? CardCssClass { get; set; }
+ ///
+ /// Height of the card view container (e.g., "500px", "70vh"). When set, the component uses its own scroll area.
+ ///
+ [Parameter]
+ public string? Height { get; set; }
+
///
/// Whether to show the filter panel above the cards. Default: false.
///
@@ -82,7 +90,22 @@ public partial class MgCardView : ComponentBase
[Parameter]
public RenderFragment? FilterPanel { get; set; }
+ ///
+ /// Item to scroll into view after render. Set to null to disable.
+ ///
+ [Parameter]
+ public TItem? ScrollToItem { get; set; }
+
+ ///
+ /// Key selector for identifying items (e.g., item => item.Id). Required when ScrollToItem is used.
+ ///
+ [Parameter]
+ public Func? ItemKeySelector { get; set; }
+
private int _activePageIndex;
+ private object? _lastScrolledKey;
+
+ private string? ContainerStyle => Height is not null ? $"height: {Height};" : null;
private IReadOnlyList PagedItems
{
@@ -108,4 +131,33 @@ public partial class MgCardView : ComponentBase
{
_activePageIndex = newPageIndex;
}
+
+ ///
+ /// Generates a stable DOM element id for a card item using the key selector.
+ ///
+ private string? GetCardElementId(TItem item)
+ {
+ return ItemKeySelector is null ? null : $"mg-card-{ItemKeySelector(item)}";
+ }
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if (ScrollToItem is not null && ItemKeySelector is not null)
+ {
+ var key = ItemKeySelector(ScrollToItem);
+ if (!Equals(key, _lastScrolledKey))
+ {
+ _lastScrolledKey = key;
+ var elementId = $"mg-card-{key}";
+ try
+ {
+ await JSRuntime.InvokeVoidAsync("MgCardView.scrollToElement", elementId);
+ }
+ catch (JSException)
+ {
+ // JS might not be loaded yet
+ }
+ }
+ }
+ }
}
diff --git a/AyCode.Blazor.Components/Components/CardViews/MgCardView.razor.css b/AyCode.Blazor.Components/Components/CardViews/MgCardView.razor.css
index 949e96e..048e9cb 100644
--- a/AyCode.Blazor.Components/Components/CardViews/MgCardView.razor.css
+++ b/AyCode.Blazor.Components/Components/CardViews/MgCardView.razor.css
@@ -1,3 +1,15 @@
+.mg-card-view-container {
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+}
+
+.mg-card-scroll-area {
+ flex: 1;
+ overflow-y: auto;
+ padding-right: 4px;
+}
+
.mg-card-grid {
display: grid;
gap: 1rem;
diff --git a/AyCode.Blazor.Components/wwwroot/js/mgCardView.js b/AyCode.Blazor.Components/wwwroot/js/mgCardView.js
new file mode 100644
index 0000000..7aa0512
--- /dev/null
+++ b/AyCode.Blazor.Components/wwwroot/js/mgCardView.js
@@ -0,0 +1,18 @@
+// MgCardView - Scroll handling
+window.MgCardView = {
+ scrollToElement: function (elementId) {
+ const element = document.getElementById(elementId);
+ if (!element) return;
+
+ // Find the closest scroll container
+ const scrollArea = element.closest('.mg-card-scroll-area');
+ if (scrollArea) {
+ const containerRect = scrollArea.getBoundingClientRect();
+ const elementRect = element.getBoundingClientRect();
+ const offset = elementRect.top - containerRect.top - (containerRect.height - elementRect.height) / 2;
+ scrollArea.scrollBy({ top: offset, behavior: 'smooth' });
+ } else {
+ element.scrollIntoView({ behavior: 'smooth', block: 'center' });
+ }
+ }
+};