4

new to Blazor and MudBlazor. I have picked up a Blazor project that is using MudBlazor for the UI. I have a requirement to be able to dynamically create a sortable, orderable and filterable table and I am told that I need to use MudBlazor to do this. Previously I have been easily able to do this using Javascript and HTML but my problem is I dont quite understand how to create a table dynamically using MudBlazor and their own documentation is not very clear either. This is what I am trying to do:

<MudTable ServerData="@(new Func<TableState, Task<TableData<EntityRowDto>>>(GetEntityRowData))" @ref="rowTable" Elevation="1" Hover Striped Loading>
<HeaderContent>
    @{
        for (int i = 0; i < rowTable.Items.ElementAt(0).SourceRowJsonProperties.Keys.Count; i++)
        {
            <MudTh>@rowTable.Items.ElementAt(0).SourceRowJsonProperties.ElementAt(i).Key</MudTh>
        }
    }
</HeaderContent>
<RowTemplate>
    @{
        for (int outer = 0; outer < rowTable.Items.Count(); outer++)
        {
            @for (int i = 0; i < rowTable.Items.ElementAt(outer).SourceRowJsonProperties.Keys.Count; i++)
            {
                <MudTd>@rowTable.Items.ElementAt(outer).SourceRowJsonProperties.ElementAt(i).Value</MudTd>
            }
        }
    }
</RowTemplate>
<NoRecordsContent>
    <MudText>No rows found</MudText>
</NoRecordsContent>
<LoadingContent>
    <MudText>
        Loading...
    </MudText>
</LoadingContent>
<PagerContent>
    <MudTablePager />
</PagerContent>
@code {
private MudTable<EntityRowDto>? rowTable;

private async Task<TableData<EntityRowDto>> GetEntityRowData(TableState state)
{
    var pageNumber = state.Page == 0 ? 1 : state.Page;
    var url = $"api/entityrow?pageNumber={pageNumber}&pageSize={state.PageSize}";

    var response = await Http.GetFromJsonAsync<PagedResponse<EntityRowDto>>(url);

    return new TableData<EntityRowDto>
        {
            TotalItems = response?.Metadata.TotalItemCount ?? 0,
            Items = response?.Items ?? Enumerable.Empty<EntityRowDto>()
        };
}

}

This compiles ok but it errors when I run it and I assume it is because I am not accessing the data context correctly for the MudTable?

blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: Value cannot be null. (Parameter 'source') System.ArgumentNullException: Value cannot be null. (Parameter 'source') at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument) at System.Linq.Enumerable.ElementAt[EntityRowDto](IEnumerable`1 source, Int32 index) at Deltafs.Integrations.Dashboard.Client.Components.EntityRows.EntityRowTable.b__0_0(RenderTreeBuilder __builder2) in C:\Data Migration V2\DataMigration.Reporting\Deltafs.Integrations.Dashboard.Client\Components\EntityRows\EntityRowTable.razor:line 10

Is what I am trying to do possible? How do I access the data context for the mudTable once it has been assigned?

Any advice greatly appreciated.

6
  • 1
    I suggest you try to get first the data necessary to define the header and row contents, and only then you give the data to the MudBlazor table. The table is probably processing HeaderContent and RowTemplate before getting the data through ServerData. Commented Jul 8, 2022 at 16:01
  • Did you figure this out? Commented Jul 30, 2022 at 12:04
  • 1
    Sorry, forgot to update the ticket, yes I did figure this out using the the suggestion given by T.Trassoudaine. I used a flag and named it 'isLoaded'. By default it is set to false and only gets set to true inside 'GetEntityRowData'. In my MudTable code I then check if the flag 'isLoaded' is set to true before trying to enumerate the data and this works exactly as I need it to. Commented Aug 2, 2022 at 9:45
  • 1
    @Reggie - It would be so much appreciated if you reply to your question and share a sample code. Thanks in advance. Commented Apr 1, 2023 at 3:45
  • @Reggie Any chance you have a sample of this code? Trying to do the same thing myself and having issues. Commented Mar 18, 2024 at 15:25

1 Answer 1

0

UPDATE: this was quite a while ago on an old project of mine but here is an example of the code I used on a page using the 'isLoaded' flag as mentioned in my comments. Hopefully it is self explanatory but could well be out of date Blazor wise, hope it helps:

<MudTable ServerData="@(new Func<TableState, Task<TableData<SchemaRowDto>>>(GetTableDataAsync))" Elevation="1" Dense Hover>
<HeaderContent>
    @{
        if (isLoaded && headers != null)
        {
            foreach (var header in headers)
            {
                <MudTh>@header</MudTh>
            }
        }
    }
</HeaderContent>
<RowTemplate>
    @{
        if (isLoaded && headers != null)
        {
            foreach (var header in headers)
            {
                var kvp = context.MessageSchemaEntityJsonProperties.Where(x => x.Key == header).FirstOrDefault();

                if (kvp.Key != null)
                {
                    var key = kvp.Key;
                    var val = kvp.Value;

                    if (JsonHelper.IsComplexObject(val))
                    {
                        <MudTd Style="text-align:center">
                            <MudIconButton Title="More Information"
                                           Icon="@Icons.Filled.OpenInNew"
                                           OnClick="@(() => OpenDialog(key, val))"
                                           Color="Color.Info"
                                           Size="Size.Small">
                            </MudIconButton>
                        </MudTd>
                    }
                    else
                    {
                        <MudTd DataLabel="@key">@val</MudTd>
                    }
                }
                else
                {
                    <MudTd></MudTd>
                }
            }
        }
    }
</RowTemplate>
<NoRecordsContent>
    <MudText>No rows found</MudText>
</NoRecordsContent>
<LoadingContent>
    <MudText>
        Loading...
    </MudText>
</LoadingContent>
<PagerContent>
    <MudTablePager />
</PagerContent>
@code {
[Parameter]
public Guid MigrationId { get; set; }

[Parameter]
public Guid? LogMessageLookupId { get; set; }

[Parameter]
public string AreaName { get; set; }

private bool isLoaded = false;
private IList<string>? headers;

private async Task<TableData<SchemaRowDto>> GetTableDataAsync(TableState state)
{
    var url = $"api/schema-row-log-message?migrationId={MigrationId}&areaName={AreaName}&hasLogMessageLookupId={LogMessageLookupId}&pageNumber={state.Page + 1}&pageSize={state.PageSize}";
    var response = await Http.GetFromJsonAsync<PagedResponse<SchemaRowDto>>(url);

    headers = response?.Items.SelectMany(x => x.MessageSchemaEntityJsonProperties.Keys).Distinct().ToList();

    if (headers?.Count > 0)
    {
        // Make sure SourceKey is always first in the list
        var hasSourceKey = headers.Remove("SourceKey");
        if (hasSourceKey)
        {
            headers.Insert(0, "SourceKey");
        }
    }

    isLoaded = true;

    return new TableData<SchemaRowDto>
    {
        TotalItems = response?.Metadata.TotalItemCount ?? 0,
        Items = response?.Items ?? Enumerable.Empty<SchemaRowDto>()
    };
}

    private void OpenDialog(string header, object val)
{
    var parameters = new DialogParameters();
    parameters.Add("ContentText", JsonHelper.ToPrettyString(val.ToString()));

    DialogService.Show<DialogScrollable>(header, parameters);
}

}

Sign up to request clarification or add additional context in comments.

1 Comment

You should be able to use <MudTable ServerData="GetTableDataAsync" ref=...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.