I want to test if it was possible to create Blazor components dynamically.
I can't find any way to do this. I have experimented a bit with some dynamic content found on this link but have not ended up with any results.
Let's create a Blazor component to display details about the employees of an organization. To add a component to the project, right-click on the Pages folder and choose Add -> Razor Component. Refer to the following image. In the Add New Item- Blazor App dialog, provide the name EmployeeCard and click Add.
In the Blazor application, a component can also be nested inside another component using the HTML syntax. For example, if you want to nest counter component inside the index component then you need to use <Counter /> within the Index component.
In the method you check if it´s a single left click, single right click, double left etc. and fill your string variable accordingly (e. g. stringClicked = "leftsingle" ). Then you can show components by evaluating the value of a string variable.
Judging by the comments on the accepted answer and on the original version of this answer I think there may be a bit of confusion around dynamically adding components. There are (at least) a couple of ways to achieve this (and a number of existing questions on this, e.g. here). It all depends on exactly what you mean by 'dynamically':
If what you're trying to achieve is simply to show or hide components based on some state in your data or model, then the 'normal' way to render a component dynamically is to use some sort of conditional code in your Razor view.
@if (_showCounter) { <MyCounterComponent Count="@_count" /> } @code { bool _showCounter = true; int _count; }
For repeating sets of data, such as lists of items you can take advantage of Blazor's data binding.
Take the example of a page/component that shows a sales order and then has a child component for each sales order line. You might have code that looks like this on your razor page:
@foreach (var salesOrderLine in _salesOrder.salesOrderlines) { <SalesOrderLine SOLine=@salesOrderLine /> };
If you had a button that added another sales order line then you could simply add the new record to the _salesOrder
model/view model in that buttons click event. Button clicks normally trigger a re-render, so the page should then automatically show an extra SalesOrderLine
component (and if it doesn't you can use this.StateHasChanged();
to tell it things are different and cause a re-render)
If your list contains different types you can use a switch statement to decide which type of component to render, e.g. (from this GitHub question):
<ul> @foreach (fruit in fruits) { switch(fruit) { case PearComponent p: <PearComponent ParameterOfSomeSort="p"></PearComponent> <li>Or render pears like this, if you want the li in it</li> break; case AppleComponent a: <AppleComponent></AppleComponent> break; case BananaComponent b: <BananaComponent></BananaComponent> break; case RaspberryComponent r: <RaspberryComponent></RaspberryComponent> break; } } </ul>
There are some cases that can't be handled well using the Razor approach above. In those cases RenderFragment
offers another way to dynamically render parts of a page.
Where you have a truly polymorphic list (e.g. a list of objects that all implement the same interface or inherit from the same class) then this type of approach can be used from this GitHub post:
@page "/" @foreach (CounterParent counter in components) { RenderFragment renderFragment = (builder) => { builder.OpenComponent(0, counter.GetType()); builder.CloseComponent(); }; <div> <div>Before the component</div> @renderFragment <div>Afterthe component</div> </div> } @code { List<CounterParent> components = new List<CounterParent>() { new CounterParent(), new CounterChild() }; }
The Blazor team are considering improving how polymorphic lists are handled in Blazor:
mkArtakMSFT commented on 1 Oct 2019 Thanks for contacting us, @Joebeazelman. Using the switch approach you have will be our recommendation. We will consider doing something better in this area in the future.
The key point here (for those from an MVC background) is that there's no need to try and manually inject the new HTML into the DOM, or dynamically load a partial view, in the way you might of in MVC, Blazor will do that for you.
Despite the similarity in syntax between razor pages for MVC and those for Blazor, the Blazor model is conceptually much closer to something like React than it is to MVC, it's really important to understand there's something along the lines of a shadow-DOM in the background.
This page has some good pointers on data binding in Blazor.
For version 0.2 this is the answer from Steve Sanderson:
We'll implement nicer APIs to build RenderFragments in the future, but for now you can
@CreateDynamicComponent(); @functions { RenderFragment CreateDynamicComponent() => builder => { builder.OpenComponent(0, typeof(SurveyPrompt)); builder.AddAttribute(1, "Title", "Some title"); builder.CloseComponent(); }; }
Those are very low-level APIs (not even documented) so we hope not many people need to do this right now. Higher-level APIs for this will come later.
Found here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With