Skip to content

Mewgrammer/BlazingComponents

Repository files navigation

Build

Branch Status
master Build status
dev Build status

Table of Contents

  1. Getting Started
  2. Authentication Library
    1. Getting Started
    2. User State
    3. User Controller
    4. User Service
  3. Component Library
    1. Getting Started
    2. Auto Table
    3. Blazor Table
    4. Blazor Gallery
    5. Blazor List
    6. Blazor Tree
    7. Navigation
    8. Expandable Container
    9. Notifications / Toasts
  4. Credits
  5. License

NuGet Packages

There are 2 Packages available on Nuget.org

BlazingComponents.Authentication

This Package includes support for basic authentication in Blazor.

  • User Controller for basic Authentication
  • UserStateProvider for use in Components
  • Components for Login & Register
  • Basic User Service to test Authentication with Users stored in Memory

BlazingComponents.Lib

This Project contains various Components for Blazor. All Components can be used on Client-side or Server-side blazor.

Included Components

  • AutoTable - Automatically generates a Table using reflection
  • BlazorTable - Generates a table based on Template Parameters
  • Expandable Container - Supports Animated Expansion/Collapse of Content
  • Gallery - Gallery Component with Data Source
  • Nav Bar - Horizontal Navigation
  • Nav Menu - Vertical Navigation
  • UIList - List Component with Data Source
  • UITree - Tree Component with various Eventhandlers and Data Source
  • Progressbar - Spinner and various Progressbars

Authentication Package

Getting Started (Authentication)

Download the NuGet Package BlazingComponents.Authentication

Imports

Namespaces for Imports:

  • BlazingComponents.Authentication.Areas.Components
  • BlazingComponents.Authentication.Services
  • BlazingComponents.Authentication.Models
  • BlazingComponents.Authentication.Interfaces

Startup.cs

        public void ConfigureServices(IServiceCollection services)
        {
            //...
            services.AddAuthentication("BasicAuthentication")
                .AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("BasicAuthentication", null)
                .AddCookie();
            services.AddAuthorization();
            services.AddControllers()
                .AddApplicationPart(typeof(UserController).GetTypeInfo().Assembly)
                .AddControllersAsServices();
            services.AddSingleton<IUserService, BasicUserService>();

            services.AddScoped(s =>
            {
                // Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it.
                var uriHelper = s.GetRequiredService<IUriHelper>();
                return new HttpClient
                {
                    BaseAddress = new Uri(uriHelper.GetBaseUri())
                };
            });
            //...
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            //...
            app.UseAuthentication();
            app.UseAuthorization();
            //...
        }

App.razor

    <UserStateProvider>
        <Router AppAssembly="typeof(Startup).Assembly" />
    </UserStateProvider>

User State

public class UserState
{
    public string Id { get; set; }
    public string DisplayName { get; set; }
    public bool IsLoggedIn { get; set; }
    public EUserRole Role { get; set; }
    public IDictionary<string, object> UserData { get; set; }
}

UserController

The User Controller will bind to /user, /login, and /register. The UserStateProvider will call these Controller-functions to perform logged-in state-check, login and registration. When replacing the User Controller, make sure the URL stays the same and return a UserState object as it is currently hard coded into the UserStateProvider.

[HttpGet("user")]
public ActionResult<UserState> GetUser();
[HttpGet("login")]
public async Task<ActionResult<UserState>> Login();
[HttpPost("register")]
public async Task<ActionResult<UserState>> Register(UserCredentials userCredentials);
[HttpPut("logout")]
public async Task<ActionResult<UserState>> SignOut();

IUserService

Feel free to replace the BasicUserService with your own implementation of IUserService.

public interface IUserService
{
    Task<UserState> RegisterAsync(UserCredentials credentials);
    Task<UserState> LoginAsync(UserCredentials credentials);

}

BasicAuthenticationHandler

The BasicAuthenticationHandler receives a instance of IUserService via Dependency Injection.

Component Library Package

Getting Started (Component Lib)

Download the NuGet Package BlazingComponents.Lib

Imports

Namespaces for Imports:

  • BlazingComponents.Lib.Areas.Components
  • BlazingComponents.Lib.Services
  • BlazingComponents.Lib.Models

_Host.cshtml

Your _Host.cshtml should look somewhat like this:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <title>Your Title Here</title>
            <base href="~/" />
            <link href="_content/BlazingComponents.Lib/libs/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
            <link href="_content/BlazingComponents.Lib/libs/fontawesome/css/all.min.css" rel="stylesheet" />
            <link href="_content/BlazingComponents.Lib/css/toast.css" rel="stylesheet">
            <link href="_content/BlazingComponents.Lib/css/site.css" rel="stylesheet" />
        </head>
        <body>
            <app>@(await Html.RenderComponentAsync<App>())</app>
            <script src="_framework/blazor.server.js"></script>
            <script type="text/javascript" src="_content/BlazingComponents.Lib/libs/jquery/jquery.min.js"></script>
            <script type="text/javascript" src="_content/BlazingComponents.Lib/libs/bootstrap/js/bootstrap.min.js"></script>
        </body>
    </html>

App.razor

    <Router AppAssembly="typeof(Startup).Assembly" />
    <ToastContainer />

Startup.cs

Edit your Startup.cs like this:

public void ConfigureServices(IServiceCollection services)
{
    //...
    services.AddComponentLib();
    services.AddScoped(s =>
    {
        // Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it.
        var uriHelper = s.GetRequiredService<IUriHelper>();
        return new HttpClient
        {
            BaseAddress = new Uri(uriHelper.GetBaseUri())
        };
    });
    //...
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //...
    app.UseAuthentication();
    app.UseAuthorization();
    //...
}

Auto Table

Parameters

Name Type Description
ItemKeyDelegate Func<T, object> Delegate to pass to the @key directive for each item in a row
ExpandedItemKeyDelegate Func<T, object> Delegate to pass to the @key directive for each item in the expanded content of a Row
TableClass string CSS-class for the table element
SelectedClass string CSS-class for the row when it is in the selected state
Properties IEnumerable List the properties to use for column-generation (default: all properties are used)
ExpandedRowTemplate RenderFragment Render Fragment for table expanded row content
Items IReadOnlyList Items to be used for table-row generation
Selectable bool Determines whether rows should be selectable
Expandable bool Determines whether rows should be expandable
MultiSelect bool Determines whether multiple rows should be selectable
MultiExpand bool Determines whether multiple rows should be expandable
SelectedItems IList The selected items
ExpandedItems IList The expanded items
OnSelect EventCallback emitted when a row is selected
OnExpand EventCallback emitted when a row is expanded
OnSelectMany EventCallback<IEnumerable> emitted when a row or multiple rows are selected
OnExpandMany EventCallback<IEnumerable> emitted when a row or multiple rows is expanded

Example

<AutoTable Items="Persons" Selectable="true" MultiSelect="false">
    <ExpandedRowTemplate Context="person">
        <td colspan="6">
            @($"{person?.FirstName} {person.LastName} born on {person?.BirthDate}")
        </td>
    </ExpandedRowTemplate>
</AutoTable>

Blazor Table

Parameters

Name Type Description
ItemKeyDelegate Func<T, object> Delegate to pass to the @key directive for each item in a row
ExpandedItemKeyDelegate Func<T, object> Delegate to pass to the @key directive for each item in the expanded content of a Row
TableClass string CSS-class for the table element
SelectedClass string CSS-class for the row when it is in the selected state
TableHeader RenderFragment Render Fragment for table header
RowTemplate RenderFragment Render Fragment for table row content
ExpandedRowTemplate RenderFragment Render Fragment for table expanded row content
TableFooter RenderFragment Render Fragment for table footer
Items IReadOnlyList Items to be used for table-row generation
Selectable bool Determines whether rows should be selectable
Expandable bool Determines whether rows should be expandable
MultiSelect bool Determines whether multiple rows should be selectable
MultiExpand bool Determines whether multiple rows should be expandable
UsePagination bool Determines whether the table should have pagination
ItemsPerPageOptions bool The available options for items per page in the pagination
SelectedItems IList The selected items
ExpandedItems IList The expanded items
OnSelect EventCallback emitted when a row is selected
OnExpand EventCallback emitted when a row is expanded
OnSelectMany EventCallback<IEnumerable> emitted when a row or multiple rows are selected
OnExpandMany EventCallback<IEnumerable> emitted when a row or multiple rows is expanded

Example

<BlazorTable @ref="_tableComponent" Items="Persons" UsePagination="true" Expandable="true" Selectable="true" MultiSelect="true" MultiExpand="false">
        <TableHeader>
            <th></th>
            <th>ID</th>
            <th>FirstName</th>
            <th>LastName</th>
            <th>BirthDate</th>
        </TableHeader>
        <RowTemplate Context="person">
            <td>@person.Id</td>
            <td>@person.FirstName</td>
            <td>@person.LastName</td>
            <td>@person.BirthDate</td>
        </RowTemplate>
        <ExpandedRowTemplate Context="person">
            <td colspan="6">
                <table class="table">
                    <thead>
                        <tr>
                            <th>ToString</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>
                                @person
                            </td>
                        </tr>
                    </tbody>
                </table>
            </td>
        </ExpandedRowTemplate>
    </BlazorTable>

Blazor Gallery

Gallery Item Model

    public class GalleryItem<T>
    {
        public string ImageSource { get; set; }
        public T Data { get; set; }
        public string Title { get; set; }
        public string Subtitle { get; set; }
    }

Parameters

Name Type Description
Items List<GalleryItem> Gallery-Items to be used for the gallery
OnSelect EventCallback emitted when a gallery-item is selected

Example

    <BlazorGallery @ref="_gallery" Items="GalleryItems" />
        public GalleryItem<string> CurrentItem { get; set; }

        public List<GalleryItem<string>> GalleryItems { get; set; } = new List<GalleryItem<string>>
        {
            new GalleryItem<string> { Data = "Hello I am item 1", ImageSource = "http://wowslider.com/sliders/demo-93/data1/images/sunset.jpg", Subtitle = "Subtile of Item 1", Title = "Item 1"},
            new GalleryItem<string> { Data = "Hello I am item 2", ImageSource = "http://wowslider.com/sliders/demo-93/data1/images/sunset.jpg", Subtitle = "Subtile of Item 2", Title = "Item 2"},
            new GalleryItem<string> { Data = "Hello I am item 3", ImageSource = "http://wowslider.com/sliders/demo-93/data1/images/sunset.jpg", Subtitle = "Subtile of Item 3", Title = "Item 3"}
        };

Blazor List

Parameters

Name Type Description
ItemKeyDelegate Func<T, object> Delegate to pass to the @key directive for each item in the list
ExpandedItemKeyDelegate Func<T, object> Delegate to pass to the @key directive for each item in the expanded content of a List Entry
CssClass string CSS-class for the list (default: "list-group")
ItemCssClass string CSS-class for the list items (default: "list-group")
SelectedCssClass string CSS-class for the items when they are in the selected state (default: "list-group-item active")
ItemTemplate RenderFragment Render Fragment for list item content
ExpandedItemTemplate RenderFragment Render Fragment for expanded list item content
Items IReadOnlyList Items to be used for table-row generation
Selectable bool Determines whether items should be selectable
Expandable bool Determines whether items should be expandable
MultiSelect bool Determines whether multiple items should be selectable
MultiExpand bool Determines whether multiple items should be expandable
SelectedItems IList The selected items
ExpandedItems IList The expanded items
OnSelect EventCallback emitted when a item is selected
OnExpand EventCallback emitted when a item is expanded
OnSelectMany EventCallback<IEnumerable> emitted when a item or multiple items are selected
OnExpandMany EventCallback<IEnumerable> emitted when a item or multiple items is expanded

Example

<BlazorList @ref="_listRef" Items="@ListItems" Selectable="true" MultiSelect="false" Expandable="true" MultiExpand="false">
    <ItemTemplate Context="item">
        <span>@item.FirstName  @item.LastName , @item.BirthDate</span>
        <button class="btn btn-outline-dark" @onclick="@( () => ExpandItem(item))">Expand</button>
    </ItemTemplate>
    <ExpandedItemTemplate Context="item">
        <ul class="list-group bg-dark text-white">
            <li class="list-group-item list-group-item-dark text-white bg-dark">
                <span>@item.ToString()</span>
            </li>
        </ul>
    </ExpandedItemTemplate>
</BlazorList>

Blazor Tree

Node Model Class

public class BlazorTreeNode<T>
    {
        public int Id { get; set; }
        public T Data { get; set; }
        public BlazorTreeNode<T> Parent { get; set; }
        public List<BlazorTreeNode<T>> Children { get; set; } = new List<BlazorTreeNode<T>>();
        public int Deep { get; set; }
        public string Text { get; set; }
        public bool IsExpanded { get; set; } = false;
        public bool IsSelected { get; set; } = false;
        public bool ChildrenLoaded { get; set; } = false;
        public bool IsVisible { get; set; } = true;
    }

Parameters

Name Type Description
NodeKeyDelegate Func<BlazorTreeNode, object> Delegate to pass to the @key directive for each node
LazyLoadNodesAsyncDelegate Func<int?, Task<List<BlazorTreeNode>>> Delegate for lazy loading nodes asynchronously on init
Nodes List<BlazorTreeNode> List of nodes
OnSelect EventCallback<BlazorTreeNode> emitted when a node is selected
OnExpand EventCallback<BlazorTreeNode> emitted when a node is expanded
OnCollapse EventCallback<BlazorTreeNode> emitted when a node is collapsed

Example

<BlazorTree @ref="_treeRef"  Nodes="@_nodes">
</BlazorTree>
public List<BlazorTreeNode<string>> _nodes = new List<BlazorTreeNode<string>>(){
    new BlazorTreeNode<string>()
    {
        Text = "Node 1", Children = new List<BlazorTreeNode<string>>()
    {
            new BlazorTreeNode<string>() { Text = "ChildNode 1"},
            new BlazorTreeNode<string>() { Text = "ChildNode 2"},
            new BlazorTreeNode<string>() { Text = "ChildNode 3"},
            new BlazorTreeNode<string>() {
                Text = "ChildNode 4", Children = new List<BlazorTreeNode<string>>()
            {
                    new BlazorTreeNode<string>() { Text = "Nested ChildNode 1"},
                    new BlazorTreeNode<string>() { Text = "Nested ChildNode 2"},
                    new BlazorTreeNode<string>() { Text = "Nested ChildNode 3"},
                }
            },
        }
    }
};

Blazor Progress

Progress Types

public enum EProgressType
{
    Spinner, 
    Progress,
    Animated
}

Parameters

Name Type Description
ProgressType EProgressType Progress Type (Spinner/Bar)
ProgressValue int Progress percentage between 0 and 100

Example

    <BlazorProgress ProgressType="@(EProgressType.Animated)" ProgressValue="@Progress"></BlazorProgress>
protected async Task ProgressForward()
{
    for (int i = 0; i <= 100; i += 10)
    {
        Progress = i;
        await Task.Delay(300);
        StateHasChanged();
    }
}

Navigation

Nav-Link Model

public class NavLinkItem
{
    public string DisplayName { get; set; } = "NavLink";
    public string Href { get; set; } = "";
    public string Icon { get; set; } = "fas fa-link"; // https://fontawesome.com/icons?d=gallery
    public NavLinkMatch Match { get; set; } = NavLinkMatch.All;
}

Horizontal Navigation / Navbar

Parameters

Name Type Description
Title string Title
NavLinks List Nav-Links to be displayed

Example

    <NavBar Title="Blazing Components" NavLinks="NavLinks" />

Vertical Navigation / NavMenu

Parameters

Name Type Description
NavLinks List Nav-Links to be displayed

Example

    <NavMenu NavLinks="NavLinks" />

Expandable Container

Parameters

Name Type Description
AnimateExpandClass string css class for expansion
AnimateCollapseClass string css class for collapse
Expanded bool Expanded-state
CollapsedContent RenderFragment RenderFragment for content when container is collapsed
ExpandedContent RenderFragment RenderFragment for content when container is expanded

Example

<ExpandableContainer @ref="_expandableContainerRef">
    <CollapsedContent>
        <NavMenu NavLinks="@NavLinksIconOnly" />
    </CollapsedContent>
    <ExpandedContent>
        <NavMenu NavLinks="@NavLinks" />
    </ExpandedContent>
</ExpandableContainer>

Notifications / Toasts

Toasts are displayed by using the ToastService. Inject the ToastService:

 [Inject]
 public IToaster Toaster { get; set; }

or @inject Sotsera.Blazor.Toaster.IToaster Toaster

Example

public ShowToastOnSignalRConnectionStateChange(){
    SignalRClient.ConnectionStateChanged += (state) =>
        {
            if (SignalRClient.IsConnected)
            {
                Toaster.Success("SignalR connection established");
            }
            else if(state == Microsoft.AspNetCore.SignalR.Client.HubConnectionState.Reconnecting)
            {
                Toaster.Warning("SignalR connection unstable");
            }
            else
            {
                Toaster.Error("SignalR disconnected");
            }
        };
}

License

BlazingComponents is licensed under MIT license

Credits

Components are styled using the awesome Bootstrap 4 Library

BlazingComponents.Authentication uses Bcrypt.Net-Core to secure Passwords

This Project was created in collaboration with Insite GmbH & Reutlingen University (Hochschule Reutlingen), Faculty Informatics - Medien & Kommunikationsinformatik in the lecture "MKI Projekt: Cloud-in-a-Box" Special thanks to Prof. Dr. Hertkorn for his support and making this project possible.

If you find any problems/bugs or notice any bad practices feel free to open a issue.