Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blazor - How to create Components dynamically

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.

like image 941
Diemauerdk Avatar asked May 01 '18 14:05

Diemauerdk


People also ask

How do you create a component in Blazor?

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.

Can Blazor components be nested?

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.

How do you render a component on button click in Blazor?

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.


2 Answers

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':

1) Using conditional statements in your Razor code

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.

Simple conditional rendering

@if (_showCounter) {   <MyCounterComponent Count="@_count" /> }  @code {   bool _showCounter = true;   int _count; } 

Simple repeating data sets

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)

Repeating data sets containing different data types (possibly polymorphic)

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> 

2. Dynamic rendering using RenderFragment

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.

Polymorphic lists

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.

Conclusion

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.

like image 170
tomRedox Avatar answered Oct 05 '22 23:10

tomRedox


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

like image 38
Flores Avatar answered Oct 06 '22 01:10

Flores