Front

Mateusz Turzyński / Michał Michalczuk

Czym jest Blazor?

Michał
Michalczuk

Mateusz
Turzyński

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">
  Click me
</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

?

App.dll

.NET

(mscorlib.dll, System.core.dll etc)

WebAssembly

(mono.wasm)

.cs

.razor

Kompilacja

Co potrafi Blazor?

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<InputNumber @bind="@currentCount" />

<button class="btn btn-primary" @onclick="IncrementCount">
  Click me
</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

Dzień z życia programisty

tworzymy formularz ;)

public class PersonModel
{
	[Required]
	[Range(18, 60, 
    	ErrorMessage = "Either too old or too young :(")]
	public int Age { get; set; }

	[Required]
	[MinLength(5)]
	[MaxLength(15)]
	public string FullName { get; set; }
    
	public string Password { get; set; }

	[Compare(nameof(Password))]
	public string RepeatPassword { get; set; }    
}
@inject HttpClient Http

@code {
    private PersonModel person = new PersonModel();
    
    private async Task HandleValidSubmit()
    {
        await Http.PostJsonAsync("/api", person);
    }

    private void HandleInvalidSubmit()
    {
        Console.WriteLine("The form is not valid :(");
    }
}
<EditForm Model="person"
          OnValidSubmit="@HandleValidSubmit"
          OnInvalidSubmit="@HandleInvalidSubmit">

    <DataAnnotationsValidator />
    <ValidationSummary />

    <h1>Personal form</h1>

    <p>
        <label>Enter your age:</label>
        <InputNumber @bind-Value="person.Age" />
    </p>
    <p>
        <label>Enter your name:</label>
        <InputText @bind-Value="@person.FullName" />
        <ValidationMessage For="@(() => person.FullName)" />
    </p>
    
    (...)
    
    <p>
        <button type="submit">Submit</button>
    </p>

</EditForm>

Style

<span>Colored span</span>

<div>Div with background</div>

<a href="#">Sample link with background</a>

<Styled>
    span {
        color: pink:
    }

    div {
        background: green;
        color: white;
    }

    a {
        background: blue;
    }
</Styled>

@code {}

Obsługa routingu

@page "/simple-routing/{text}"
@page "/advanced-routing/{counter:int}"

<p>Text from parameter: @Text</p>
@if (Counter.HasValue)
{
    <p>Counter: @Counter</p>
}

@code {

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

    [Parameter]
    public int? Counter { get; set; }
}
<NavLink href="simple-form" 
         Match="NavLinkMatch.All" 
         class="nav-link">
    Simple form
</NavLink>
<NavLink href="simple-routing/test" 
         Match="NavLinkMatch.Prefix" 
         class="nav-link" >
    Simple routing
</NavLink>

Model komponentowy

<div>

    <p>Hello @FullName</p>

    <button @onclick="OnDeleteAccount">
        Delete my account
    </button>

</div>

@code {

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

    [Parameter]
    public EventCallback OnDeleteAccount { get; set; }
}
@page "/person"

@if (accountDeleted)
{
    <p>Account deleted</p>
}
else
{
    <PersonDetails FullName="John Rambo"
                   OnDeleteAccount="() => AccountDeleted()" />
}

@code {

    private bool accountDeleted;

    private void AccountDeleted()
    {
        accountDeleted = true;
    }
}

Ale jak to połączyć

z JavaScript?

JavaScript interop

// index.html
<script>
  window.getElementDimensions = selector => {
      try {
          const element = document.querySelector(selector);

          if (!element) {
              return null;
          }

          return {
              height: element.scrollHeight,
              width: element.scrollWidth
          };
      } catch (ex) {
          return null;
      }
  };
</script>
// UseJavaScript.razor
@inject IJSRuntime JSRuntime;

...

@code {
    class BrowserSize {
        public int Height { get; set; }
        public int Width { get; set; }
    }

    private string Selector { get; set; } = "body";
    private BrowserSize ClientSize { get; set; } = new BrowserSize();

    private async Task UpdateSize() 
    {
        var jsResult = await JSRuntime.InvokeAsync<BrowserSize>(
            "getElementDimensions", 
            Selector
        );

        ClientSize = jsResult != null ? jsResult : new BrowserSize();

        StateHasChanged();
    }
}

3rd party JS

// index.js
import { Chart } from 'chart.js';
import 'chartjs-plugin-labels';

export const charts = {
  drawChart: (canvasSelector, type, { data = [], labels = [] }) => {
    const canvas = document.querySelector(canvasSelector).getContext('2d');

    new Chart(canvas, {
      ....
    });
  }
};
const path = require('path');

module.exports = {
  module: {
    rules: [
      {
        test: /\.(js)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  },
  output: {
    path: path.resolve(__dirname, '../wwwroot/js'),
    filename: 'js-lib.js',
    library: 'FrontNetJS'
  }
};
@inject IJSRuntime JSRuntime;

<canvas id="chart-canvas"></canvas>

@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender) 
        {
            await InitializeChart();
        }
    }

    private async Task InitializeChart() 
    {
        await JSRuntime.InvokeVoidAsync("FrontNetJS.charts.drawChart", 
            "#chart-canvas", 
            "pie",
            new {
                Data = new List<int> { 100, 200, 300, 400},
                Labels = new List<string> { "A", "B", "C", "D" }
            }
        );
        StateHasChanged();
    }
}

Browser

UI Thread

Blazor

Blazor jest jednowątkowy

Czym jest Blazor?

jest runtimem .NET

jest frameworkiem SPA

Blazor Web Assembly nie jest production ready...

...ale Blazor Server jest

Jak działa blazor server?

JavaScript interop

Blazor WASM

  • działa po stronie klienta
  • ciężkie assety
  • nie potrzebuje ciągłego połączenia z serwerem
  • potrzebuje API po stronie serwera
  • nie wymaga mocnej infrastruktury serwerowej

Blazor Server

  • działa po stronie serwera
  • mało do pobrania
  • dużo komunikacji po WS
     
  • pełni funkcje serwera API
     
  • słabo się skaluje

vs

Zastosowanie Blazor Web Assembly

Obecnie: nigdzie

Przyszłość: SPA

Daleka przyszłość: tam gdzie potrzebna jest wydajność (dzięki AoT)

Zastosowanie Blazor Server

Obecnie: intranet, dashboardy

Przyszłość: prawdopodobnie zniknie po wydaniu Blazor WASM

Co dalej?

  • Blazor Server - production ready
  • Blazor WASM - ETA 2020
  • Blazor PWA / Hybrid / Native

Q&A

Ankieta:

Made with Slides.com