Reputation: 353
I have a .NET Blazor Server app and need to pass an object from one component to another. Both components are pages, meaning that they have @page directives with routes. I know how to use cascading values to pass a parameter between regular Blazor components, but this does not work with page components. I also know how to pass a parameter within an endpoint route. However, instead of a string or int I want to pass an object with multiple properties and am unsure how to best accomplish this.
Is it possible to pass an object as an endpoint route parameter? If not, what is a good way to accomplish this within a Razor components context?
Upvotes: 2
Views: 3692
Reputation: 46
You can create a Singleton (a unique Instance of a Service Class) with Get Set properties and functions
So you Set in the current page and then Get on the next page init
First, create a Service named DataTransferService:
public class DataTransferService : IDataTransferService
{
public int Id { get; set; }
public Bag OnEditBag { get; set; }
public async Task SetIdTo(int id) { Id = id; }
public async Task<int> GetSelectedId() { return Id; }
public async void SetBagToEdit(Bag bag) { OnEditBag = bag; }
public async Task<Bag> GetBag() { return OnEditBag; }
}
Then, create the Interface (used for dependency injection):
public interface IDataTransferService
{
public Task SetIdTo(int id);
public Task<int> GetSelectedId();
public void SetBagToEdit(Bag bag);
public Task<Bag> GetBag();
}
In your MauiProgram.cs add the singleton:
builder.Services.AddSingleton<IDataTransferService, DataTransferService>();
Now you can pass entire objects from a page to the next, or previous whatever
Just remember to Set and Get in the right sequence.
Imagine I have a BagManagement Page with a list of bags and I want to edit a specific Bag, so when I click in the row I am redirected to a Page to see and edit the bags attributes and save to DB via API call:
<tbody>
@if (bags.Count > 0)
{
@foreach (Bag bag in bags)
{
<tr>
<td><button @onclick="() => ToEditBagPage(bag.Id)">@bag.TagNumber</button></td>
<td>@bag.Name</td>
<td>@bag.Description</td>
<td>@bag.PriceToRent</td>
<td>@bag.PriceToBuy</td>
<td>@bag.TimesRented</td>
</tr>
}
}
</tbody>
Fuction:
public async void ToEditBagPage(int Id)
{
Debug.WriteLine(Id + "Goooing to edit page");
await _dataTransferService.SetIdTo(Id);
_dataTransferService.SetBagToEdit(await _apiService.GetBagById(Id));
NavMan.NavigateTo($"/EditBag");
}
On the Page you want to load the object:
Bag OnEditBag = new Bag();
protected override async void OnInitialized()
{
OnEditBag = await _dataTransferService.GetBag();
}
For some reason objects returned by a GET HTTP Request are not loaded if the call is in the page code, but is loaded when I call using the Service. Also, if I try to use the route to get the Id (as mentioned in others answers) I get a fckin Unhandled Error right in my nose, plus you can't pass a object.
I dind't use the Row Index to access the already stored Bag object because I dont wanna to, jokes on you is because the User can pick and change the order (and so the Index).
Hope it helps.
Upvotes: 0
Reputation: 752
Using dependency injection would likely solve this issue for you.
Example:
You could have something like this
public interface IApplicationService
{
public Task MsgBox(string value);
}
You could have something like this:
public async Task MsgBox(string value)
{
await _JSRuntime.InvokeAsync<string>("alert", value);
}
You could have something like this
builder.Services.AddTransient<IApplicationService, ApplicationService>();
builder.Services.AddScoped<ApplicationService>();
In your _Imports.razor you can inject the class so that the pages have access to it:
@inject ApplicationService MainAppService;
Now in your razor components you should be able to do something like this:
await MainAppService.MsgBox("This is a message box");
This works in my WASM blazor app, hope it sheds some light on the server side of things 🚀
Upvotes: 5
Reputation: 30375
Use a DI service. Create a class to hold your object. Add it as a Scoped Service in Program. Use it in any component (pages are just components with a page attribute) though @inject
.
Upvotes: 2