Blazor Page Head ohne JavaScript

Vor einiger Zeit hatte ich schon einmal darüber geschrieben, wie man den Page Titel setzen kann, Dazu wurde ein Einzeiler und die JavaScript Bridge genutzt. Diesmal gibt es eine Lösung ganz ohne die unsägliche Sprache, dafür rein mit C# und HTML.

Vom Kern soll eine Art HTML Attribut in der Razor Page als Platzhalter für den HTML Head Bereich dienen, der in die Blazor Page eingebettet wird.

<HeadComponent Title="Index" Description="Beschreibung">

Für die typischen Eigenschaften des HTML Head Elements  wird eine Klasse angelegt mit entsprechenden Properties wie Titel oder Beschreibung.

Im zweiten Teil der Klasse wird eine Benachrichtigungsfunkton analog dem MVVM Model aus WPF mit dem InotifyPropertyChanged Interface. Der Grund ist recht ähnlich gelagert. Wir müssen aus der Klasse das UI benachrichtigen, damit es sich neu zeichnen kann.

Im Beispiel ist der Einfachheit halber nur die Title Eigenschaft mit der Fähigkeit Ui Update ausgestattet,

   1:  public class Head
   2:  {
   3:    private string _title;
   4:   
   5:    public string Title
   6:    {
   7:    get { return _title; }
   8:    set
   9:     {
  10:      _title = value;
  11:      PropertyChanged();
  12:     }
  13:   }
  14:  public string Description { get; set; }
  15:   
  16:  public event EventHandler PropertyChangedEvent;
  17:  public async void PropertyChanged([CallerMemberName] string feldname = null)
  18:    {
  19:     PropertyChangedEvent?.Invoke(this, EventArgs.Empty);
  20:    }
  21:  }

 

Die Klasse wird per Dependency Injection auf der Service Liste angelegt. All das wie üblich in der Datei startup.cs und per Scoped Gültigkeit für den request.

   1:  public void ConfigureServices(IServiceCollection services)
   2:  {
   3:  ...
   4:  services.AddScoped<Head>();
   5:   }

 

Letztendlich wird die Blazor Head Komponente in Visual Studio angelegt. Diese enthält den HTML Teil des Head Inner Elements samt Binding. Gebunden wird an die Instanz aus dem DI Container der Head Klasse. Und zu guter Letzt wird im Falle einer Änderung des Datenobjektes, ein Event nach oben durchgereicht. Konkret wird so im Aufrufer StateHaschanged ausgeführt, was ein HTML rerendering auslöst.

Die Parameter Attribute reichen die Property als Attribut in das HTML Element durch, das in einer Blazor/Razor Page als HTMLTag Helper bezeichnet wird.

   1:  @inject BlazorApp1Head.model.Head _Head
   2:  <title>@_Head.Title</title>
   3:  <meta name="description" content="@_Head.Description">
   4:  @code
   5:  {
   6:      [Parameter]
   7:      public string Title { get; set; }
   8:      [Parameter]
   9:      public string Description { get; set; }
  10:    
  11:      protected override async Task OnInitializedAsync()
  12:      {
  13:          _Head.Title = Title;
  14:          _Head.Description = Description;
  15:          _Head.PropertyChangedEvent +=
(_, __) => InvokeAsync(StateHasChanged);
  16:      }
  17:  }

 

In der letztendlichen Page (auch eine Komponente) wird dann die Head Componenten mit den Attributen eingesetzt, Wo ist letztendlich egal.

   1:  @page "/"
   2:  <HeadComponent Title="Index" Description="Beschreibung"></HeadComponent>
   3:  <h1>Hello, world!</h1>

Nun fehlt noch der Link zwischen endgültig gerenderten HTML und der Blazor Page. Einstiegspunkt ist eine Razor Page für die Blazor App. Im Verzeichnis Pages liegt _hosts.cshtml. Neben dem HTML Helper Html.RenderComponentAsync kann auch der einfachere und modernere Tag Helper Component genommen werden  Damit wird die Blazor Komponente in eine Razor Page eingelagert.

   1:  <head>
   2:      ...

3: <component type="typeof(HeadComponent)"

render-mode="ServerPrerendered" />

   4:  </head>
Kommentare sind geschlossen