Updated date:

Blazor Component Dynamics: Static List (Components as Items)

blazor-component-dynamics-static-list-components-as-items

Components are great in Blazor, but it is important to understand where and when to use, so that you do not overuse them. In this case you will see how they can be used as list items and we will compare this use case with the one from a previous article.

The example is quite simple, in this case we have Blazor hosted project and we display bank details for the user.

public  class TestModel
    {
        public int id { get; set; }
        public string fullname { get; set; }
        public int age { get; set; }
    }
public  class SecondTestModel
    {
            public string bankaccountid { get; set; }
            public string bankname { get; set; }
            public string email { get; set; }
            public int userid { get; set; }
    }

First we have some shared models — one for user details and one for bank details.

public static List<Shared.SecondTestModel> bankdetails = new List<Shared.SecondTestModel>()
     {
         new Shared.SecondTestModel()
         {
             userid = 1,
             bankaccountid ="xx1111",
             bankname = "test bank",
             email = "ee@m.l"
         },
         new Shared.SecondTestModel()
         {
             userid = 2,
             bankaccountid ="bb7777",
             bankname = "test bank",
             email = "ll@m.l"
         },
         new Shared.SecondTestModel()
         {
             userid = 3,
             bankaccountid ="xx3333",
             bankname = "testing bank",
             email = "rr@m.l"
         },
         new Shared.SecondTestModel()
         {
             userid = 4,
             bankaccountid ="xx2222",
             bankname = "test bank",
             email = "uu@m.l"
         },
         new Shared.SecondTestModel()
         {
             userid = 5,
             bankaccountid ="aa1111",
             bankname = "test bank",
             email = "vv@m.l"
         },
     };

public static List<Shared.TestModel> users = new List<Shared.TestModel>()
        {
            new Shared.TestModel()
            {
                id = 1,
                age = 25,
                fullname = "Test Tester"
            },
             new Shared.TestModel()
            {
                id = 2,
                age = 36,
                fullname = "Mr. Tester"
            },
              new Shared.TestModel()
            {
                id = 3,
                age = 45,
                fullname = "Mrs. Tester"
            },
               new Shared.TestModel()
            {
                id = 4,
                age = 89,
                fullname = "Mister Test"
            },
                new Shared.TestModel()
            {
                id = 5,
                age = 72,
                fullname = "Mister testing"
            },
        };

In the API project, we have a class called FakeDatabase, which contains two lists of our models. This will be the data retrieved and displayed.

  [Route("/getusers")]
       public List<Shared.TestModel> GetUsers()
        {
            return FakeDatabase.users;
        }


        [Route("/getbankdetailsforusers")]
        public Shared.SecondTestModel GetBankDetailsForUser(int id)
        {
            return FakeDatabase.bankdetails.Find(x => x.userid == id);
        }

In the controller we have a couple of routes — one for retrieving user data and the other for bank data. Normally, when you retrieve separate pieces of data, you want to use separate routes, actions, procedures for them.

Client-side

The client part basically contains all the default stuff, except for the new UserComponent.razor file.

@code {

    [Parameter]
    public BlazorApp1.Shared.TestModel user { get; set; }

    BlazorApp1.Shared.SecondTestModel bankdetails;

    protected override async Task OnParametersSetAsync()
    {
        bankdetails = await http.GetJsonAsync
            <BlazorApp1.Shared.SecondTestModel>("/getbankdetailsforusers?id=" + user.id);
    }
}

The code section for the model contains a parameter for the user and then a variable for bank details to be displayed. The user details a passed through to the component when the list is generated, we will look at that later. But, in the component, we retrieve bank details. This kind of asynchronous process allows you show some data before the other pieces are loaded and if the loading times are slow, perhaps even prevent some frustration.

@inject HttpClient http



 
    <tr>
        @if (user != null)
        {
            <td>@user.id</td>
            <td>@user.age</td>
            <td>@user.fullname</td>
        }
        @if (bankdetails != null)
        { 
            <td>@bankdetails.bankaccountid</td>
            <td>@bankdetails.bankname</td>
            <td>@bankdetails.email</td>
        }
        </tr>

The html is a piece of a table, in other words — the component is a row of a table.

@code {
    List<BlazorApp1.Shared.TestModel> users;

    protected override async Task OnInitializedAsync()
    {
        users = await http.GetJsonAsync
            <List<BlazorApp1.Shared.TestModel>>("/getusers");
    }

}

For the main page, we simply have a list of users and then on initialization we simply retrieve the data and assign it to the list.

@page "/"
@inject HttpClient http

<table style="text-align:center;">
    <thead>
        <tr><th>user id</th><th>age</th><th>full name</th>
        <th>bank account</th><th>bank name</th><th>email</th></tr>
    </thead>
    <tbody>
        @if (users != null)
        {
            @foreach (var item in users)
            {
                <UserComponent user="@item"></UserComponent>
            }
        }
    </tbody>
</table>

Main page also contain the table, in which we have rows being generated as components.

As you can see, there is quite a bit of code in those two files and had it been in one file — it would be a lot more difficult to find what you need. Also, we must not forget that this is just a sample, it is more than likely that a real world project would contain a lot more code than this. Having said all that, the big difference between this example and the one you have seen in the previous article, is the fact that we retrieve two pieces of data here, whilst in the previous it was only one. This makes a huge difference and there is certainly nothing wrong to go with no components implementation. But whenever you have an option two divide the data, you should jump on that opportunity. Another reason, as mentioned previously — is the loading time. If one piece takes longer to retrieve than the other, it is always better to provide users with a bit of a teaser — that being the first piece or pieces of data.

Related Articles