How to Display Toast Notifications After CRUD Operations in ServiceStack Blazor Using AutoQueryGrid
I’m using the ServiceStack Server Blazor project template with the AutoQueryGrid component configured as follows:
<AutoQueryGrid Model="Booking" Apis="Apis.AutoQuery<QueryBookings,CreateBooking,UpdateBooking,DeleteBooking>()" />
I want to display toast notifications to users after each CRUD operation (Create, Read, Update, Delete) is completed. I’ve tried using the DataLoaded event as shown below:
@page "/bookings"
@using ServiceStack.Blazor
@Inject ToastService Toast
Bookings
<AutoQueryGrid Model="Booking" Apis="Apis.AutoQuery<QueryBookings,CreateBooking,UpdateBooking,DeleteBooking>()" DataLoaded="OnDataLoaded"/>
@code {
bool _firstLoad = true;
async Task OnDataLoaded(List<Booking> bookings)
{
// Skip showing a toast on the initial page load
if (_firstLoad)
{
_firstLoad = false;
return;
}
await Toast.Success("✅ Operation completed successfully!");
}
}
However, this approach doesn’t work as expected. The toast notification doesn’t appear after CRUD operations. I’m using ServiceStack version 8.9.0 and prefer not to use a custom edit form template.
What is the correct way to implement toast notifications after CRUD operations using the AutoQueryGrid component in ServiceStack Blazor? Are there built-in events I should be using instead, or is there a way to create custom events for the component?
The correct approach to display toast notifications after CRUD operations in ServiceStack Blazor using AutoQueryGrid is to use the built-in operation-specific events like OnCreate, OnUpdate, and OnDelete rather than the DataLoaded event, as these events specifically trigger after each respective CRUD operation completes, allowing you to show appropriate toast notifications.
Contents
- Understanding AutoQueryGrid Events
- Built-in CRUD Operation Events
- Implementation with Toast Notifications
- Alternative Approaches
- Complete Example
Understanding AutoQueryGrid Events
The AutoQueryGrid component in ServiceStack Blazor provides several built-in events that fire specifically after CRUD operations, which is exactly what you need for displaying toast notifications. Unlike the DataLoaded event that triggers whenever data is loaded (including initial page loads and refreshes), the operation-specific events allow you to target the exact moment when a user action completes.
The DataLoaded event is meant for general data loading scenarios and doesn’t distinguish between different types of operations. This is why your current approach doesn’t work as expected - the event fires on initial load and you can’t easily differentiate between a CRUD operation and a simple data refresh.
Built-in CRUD Operation Events
AutoQueryGrid exposes the following operation-specific events that you can utilize for toast notifications:
OnCreate- Fires after a new record is successfully createdOnUpdate- Fires after an existing record is successfully updatedOnDelete- Fires after a record is successfully deletedOnSave- Fires after any save operation (create or update)
These events provide the perfect hooks for displaying toast notifications because they specifically trigger when the user completes a CRUD action, not just when data is loaded.
Key Insight: The operation-specific events pass relevant data that you can use to customize your toast messages, such as the affected record or operation results.
Implementation with Toast Notifications
Here’s the correct implementation using the built-in operation events:
@page "/bookings"
@using ServiceStack.Blazor
@inject ToastService Toast
<h3>Bookings Management</h3>
<AutoQueryGrid
Model="Booking"
Apis="Apis.AutoQuery<QueryBookings,CreateBooking,UpdateBooking,DeleteBooking>()"
OnCreate="OnCreateCompleted"
OnUpdate="OnUpdateCompleted"
OnDelete="OnDeleteCompleted"/>
@code {
async Task OnCreateCompleted(Booking createdBooking)
{
await Toast.Success($"✅ Booking '{createdBooking.Id}' created successfully!");
}
async Task OnUpdateCompleted(Booking updatedBooking)
{
await Toast.Info($"📝 Booking '{updatedBooking.Id}' updated successfully!");
}
async Task OnDeleteCompleted(Booking deletedBooking)
{
await Toast.Warning($"🗑️ Booking '{deletedBooking.Id}' deleted successfully!");
}
}
Key Benefits of This Approach:
- Specific Event Handling: Each event fires only after the corresponding CRUD operation
- Contextual Information: Events provide the affected record, allowing for personalized messages
- Clean Separation: No need to track initial loads or manually filter operations
- Better User Experience: Immediate feedback for each user action
Alternative Approaches
Using the DataGrid Underlying Events
Since AutoQueryGrid is built on top of the DataGrid component, you can also access lower-level events:
<AutoQueryGrid ...>
<ChildContent>
<DataGrid @ref="DataGrid" ... />
</ChildContent>
</AutoQueryGrid>
Then handle events from the underlying DataGrid component.
Custom Event Handlers
For more complex scenarios, you can create custom event handlers:
public partial class MyAutoQueryGrid<T> : AutoQueryGrid<T>
{
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
// Subscribe to internal events
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
// Additional event setup
}
}
Complete Example with Enhanced Features
Here’s a more complete implementation with additional features:
@page "/bookings"
@using ServiceStack.Blazor
@inject ToastService Toast
<h3>Bookings Management</h3>
<AutoQueryGrid
Model="Booking"
Apis="Apis.AutoQuery<QueryBookings,CreateBooking,UpdateBooking,DeleteBooking>()"
OnCreate="OnCreateCompleted"
OnUpdate="OnUpdateCompleted"
OnDelete="OnDeleteCompleted"
OnSave="OnSaveCompleted"
OnError="OnErrorOccurred"/>
@code {
async Task OnCreateCompleted(Booking createdBooking)
{
await Toast.Success(
$"✅ Booking created successfully!",
$"ID: {createdBooking.Id}",
"success"
);
}
async Task OnUpdateCompleted(Booking updatedBooking)
{
await Toast.Info(
$"📝 Booking updated successfully!",
$"ID: {updatedBooking.Id}",
"info"
);
}
async Task OnDeleteCompleted(Booking deletedBooking)
{
await Toast.Warning(
$"🗑️ Booking deleted successfully!",
$"ID: {deletedBooking.Id}",
"warning"
);
}
async Task OnSaveCompleted(Booking savedBooking)
{
// This fires for both create and update
await Toast.Show(
$"💾 Booking saved successfully!",
$"ID: {savedBooking.Id}",
"save"
);
}
async Task OnErrorOccurred(Exception ex)
{
await Toast.Error(
$"❌ Operation failed!",
ex.Message,
"error"
);
}
}
Toast Configuration Tips:
- Use Different Types: Utilize different toast types (Success, Info, Warning, Error) to distinguish between operations
- Include Details: Add contextual information like record IDs for better user feedback
- Handle Errors: Include error handling for failed operations
- Custom Styling: Use custom toast classes if needed
Conclusion
To implement toast notifications after CRUD operations in ServiceStack Blazor using AutoQueryGrid:
- Use Operation-Specific Events: Replace the
DataLoadedevent withOnCreate,OnUpdate, andOnDeleteevents that specifically trigger after each CRUD operation - Leverage Event Parameters: These events provide the affected record object, allowing for personalized toast messages
- Add Error Handling: Include the
OnErrorevent to handle and display operation failures - Consider User Experience: Use different toast types (Success, Info, Warning) to distinguish between different operation types
This approach provides clean, targeted event handling that gives users immediate feedback after each CRUD operation, significantly improving the user experience of your Blazor application.