nAviD
nAviD

Reputation: 3281

Passing additional data to Generic RenderFragment in Blazor component

I have a simple Blazor component which iterates over a Generic List :

@typeparam TItem;

 @foreach (var item in List)
        {
            @ElementTemplate(item); // What code should be here to pass i to the ElementTemplate????
            i++;
        }

@code {
    int i = 0;


    [Parameter] public List<TItem> List { get; set; }
    [Parameter] public RenderFragment<TItem> ElementTemplate { get; set; }
  }

I have another simple component which will get an item and an index to render data(Employee):

<div> @Index . @Person.Name </div>

@code{
    [Parameter] public Person { get; set; }
    [Parameter] public int Index { get; set; }

}

And in my main page I have the following:

<GenericList List="employees">
    <ElementTemplate>
        <Employee Person="context" Index="?"></Employee>
    </ElementTemplate>
</GenericList>

As you can see Employee component needs an Index parameter, how can I pass the Index from the GenericList component? In this example the variable 'i' should be passed to ElementTemplate as well as the Generic TItem object itself.

Upvotes: 5

Views: 11725

Answers (2)

Kristian.mariyanov
Kristian.mariyanov

Reputation: 345

You can define a complex class for your Context

In the GenericList.razon, define a class:

public class ListContext
{
    public TItem Item {get; set;}
    public int Index {get; set;}
}

and use this class as a context type for your template:

[Parameter] 
public RenderFragment<ListContext> ElementTemplate { get; set; }

then when you call this template, you can just create a new class and set the correct parameters:

@foreach (var item in List)
{
    @ElementTemplate(new ListContext{Item = item, Index = i});
    i++;
}

here is a working example of this: https://blazorrepl.com/repl/cuvakzPF21sXSZGK54

Upvotes: 3

Mister Magoo
Mister Magoo

Reputation: 8994

I find the quick/simple approach is to use a tuple as the RenderFragment context:

@foreach (var item in List)
{
  @ElementTemplate((item,i));
  i++;
}

@code {
  int i=0;
  [Parameter] public List<TItem> List { get; set; }
  [Parameter] public RenderFragment<(TItem item, int index)> ElementTemplate { get; set; }
}

Then your markup becomes:

<GenericList List="employees">
    <ElementTemplate>
        <Employee @[email protected] [email protected] [email protected]></Employee>
    </ElementTemplate>
</GenericList>

If you prefer, you could use a utility class in the GenericList instead of a tuple.

Upvotes: 10

Related Questions