Month: January 2019

More Blazor

More Blazor

To continue with our adventure into Blazor, or Razor Components, we should learn how to separate the code from the html.

The general design of Blazor Pages, is to include the page code in the @functions section of the cshtml file

@functions {
    int currentCount = 0;
 
    void IncrementCount()
    {
        currentCount++;
    }
}

But we are going to remove this section, from our Index Page, and place it in a new class called IndexBase

public class IndexBase : BlazorComponent
{
    [Inject]
    private HttpClient Http { getset; }
 
    WidgetSettingsBase[] widgets;
    protected override async Task OnInitAsync()
    {
        Console.WriteLine("OnInitAsync");
        widgets = JsonConvert.DeserializeObject<WidgetSettingsBase[]>(await Http.GetStringAsync("api/SampleData/widgets"),
            new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto });
        StateHasChanged();
    }
 
    public RenderFragment CreateDynamicComponent() => builder =>
    {
        if (widgets == nullreturn;
 
        var assm = Assembly.GetExecutingAssembly();
        var assmName = assm.GetName().Name;
 
        foreach (var widget in widgets)
        {
            var widgetType = Type.GetType($"{assmName}.Widgets.{widget.widget}");
            if (widgetType != null)
            {
                AddWidget(builder, widgetType, widget);
            }
        }
    };
 
    private static void AddWidget(RenderTreeBuilder builder, Type widget, WidgetSettingsBase settings)
    {
        var seq = 0;
        builder.OpenComponent(seq, widget);
 
        if (settings is WidgetSettings widgetSettings)
        {
            foreach (var param in widgetSettings.parameters)
            {
                seq++;
                builder.AddAttribute(seq, param.Key, param.Value);
            }
        }
        else
        {
            builder.AddAttribute(seq, "Settings", settings);
        }
        builder.CloseComponent();
    }
}

This class needs to inherit from BlazorComponent. Then we can Inherit that in the page cshtml.

@page "/"
@using System.Reflection
@using Microsoft.AspNetCore.Blazor.RenderTree
@using myDash.Shared
@using Newtonsoft.Json
@inherits IndexBase
 
<head>
    <style>
        .card {
            background-colortransparent;
            background-imagelinear-gradient(to bottom, rgba(149, 87, 29, 0.2) 0%, rgba(125, 185, 232, 0) 100%);
            background-repeatrepeat;
            border-radius10px;
            padding0px;
            margin-bottom15px;
        }
    </style>
</head>
 
<section class="container">
    <div class="row info-panel">
        @CreateDynamicComponent();
    </div>
</section>

That is all it takes. Any items that were injected using the @inject keyword, can be injected to the class by making a property and using the [Inject] attribute.

I like this separation a lot better than the code existing the cshtml. However, in some simple pages, code directly in the cshtml will be very powerful. So, I can see a use for both.