Josh
Josh

Reputation: 695

How to pass a variable into a component's @typeparam in blazor

I have created a TestComponent.razor

@typeparam TValue

@code {
    private TValue Type { get; set; }
    [Parameter] public string String { get; set; }
}

In the index.razor page I have the following:

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

<ComponentFactory.Data.SampleComponent TValue="@myType" String="@myString"></ComponentFactory.Data.SampleComponent>

@code{
    Type myType { get; set; } = typeof(string);
    string myString { get; set; } = "hello";
}

I cannot pass Type myType into TValue, unless I make myType a @typeparam of the current page

Why is this happening and is there a way to pass variables into a component's @typeparam?

Upvotes: 5

Views: 6138

Answers (1)

poke
poke

Reputation: 388273

You cannot create Blazor components using a “variable” generic type argument. Just like with normal generic types in C#, these type arguments need to be known at compile time and as such you will have to specify your type directly when creating the component.

In your case, this could look like this:

<SampleComponent TValue="string" Type="some string" String="@myString" />

Since you have used your generic type argument TValue for the property Type, you can also leave out the TValue="string" explicitly and have the compiler complete that for you:

<SampleComponent Type="some string" String="@myString" />

If you want to create a component dynamically then what you can do is to dynamically create a RenderFragment that renders the component. That way

The only way to create a generic component with a dynamic type argument at run time would be to use reflection. You can create a RenderFragment to create a component dynamically:

<div>
   @SampleComponentInstance
</div>

@code{
    RenderFragment SampleComponentInstance => builder =>
    {
        var type = typeof(SampleComponent<>).MakeGenericType(new[] { MyType });
        builder.OpenComponent(1, type);
        builder.AddAttribute(2, "String", MyString);
        builder.CloseComponent();
    };

    Type MyType { get; set; } = typeof(string);
    string MyString { get; set; } = "hello";
}

This would render the SampleComponent with the generic type argument MyType inside the div.

Upvotes: 10

Related Questions