Ein Widget ist ein Steuerelement, das von Widget erbt. Ein einfaches Widget ist hier ein Widget, dass selbständig funktioniert und keine Information aus der Seite oder aus einem anderen Widgets benötigt.

Ein Widget benötigt:

  • Das Steuerelement.
  • Einen Controller.
  • Falls der View Daten vom Controller benötigt, wird empfohlen, ein View-Model zu erstellen.
  • Ein View. Der Name der View sollte wie die Aktion heißen und in einem Ordner mit gleichem Namen des Controllers liegen.
  • Falls die View auch Custom Scripts im Browser brauchen, ein .ts Datei. Zum Beispiel NavigationMenuWidget.ts.

In diesem Beispiel wird ein einfaches Widget HelloWorldWidget erstellt.

Steuerlement

Das Widget muss von Widget erben. Widget erbt von WidgetBase und damit hat das Widget die Basis Felder und Funktionen.

In diesem Beispiel wird eine feste CSS-Klasse im Feld CssClass gesetzt und eine zweite CSS Klasse, die abhängig von einer konfigurierbaren Option Bold ist, wird durch die Überschreibung der Methode GetCssClass gesetzt.

Die Methode GetControllerParameters wird benutzt, um den Parameter textLanguage an den Controller zu übernmitteln. Der Controller könnte aber auch direkt auf die Seite und das Widget zugreifen.

Zudem muss das Widget ein ControllerName definieren.

Widgets können in ActionName die Aktion im Controller definieren. Wird dies nicht gesetzt, nutzt das Widget die Aktion „Index“.

Man kann auch Standardwerte in anderen Feldern setzen, wie hier die Höhe und Ausrichtungen. Oder wie bei den anderen Steuerelementen, so können auch hier Eigenschaften von Basisklassen modifiziert werden.

Das HelloWorldWidget braucht zusätzliche Scripts in der UI. Daher ist die Methode GetTSClassName überschrieben, um die entsprechende .ts Klasse für das Widget zu definieren.

[Serializable]
public class HelloWorldWidget : Widget
{
	[DisplayName("Fett")]
	public bool Bold { get; set; }

	[DisplayName("Sprache")]
	public string Language { get; set; }

	public HelloWorldWidget() : base()
	{
		Id = "16B8262B-0461-4871-A07A-66F74EF21559".ToGuid();
		ToolboxName = "HelloWorld";
		Icon = "earth2";
		ControllerName = nameof(HelloWorldWidget);
		Height = 300;
		HeightType = EnumWidgetHeightType.Pixel;
		HorizontalAlign = EnumHorizontalAlign.Center;
		VerticalAlign = EnumVerticalAlign.Middle;
		CssClass = "hello-world";
	}

	public override string GetTSClassName()
	{
		return "BA.Ui.Widgets.HelloWorldWidget";
	}

	public override string GetCssClass()
	{
		return base.GetCssClass() + " " + (Bold ? "bold-text" : "regular-text");
	}

	public override object GetControllerParameters()
	{
		return new { textLanguage = Language };
	}
}

View Model

Das View Model beinhaltet die Informationen, die die View benötigt.

public class HelloWorldWidgetViewModel
{
	public string SalutationText { get; set; }

	public string ToSalutate { get; set; }

	public string ErrorText { get; set; }
}

Controller

Der Controller hat eine Aktion Index, die das View Model für das Widget vorbereitet und dann die entsprechende PartialView zurückliefert. In dem Fall wird kontrolliert, ob eine Sprache konfiguriert wurde. Falls nicht, wird das Widget einen Fehlertext beinhalten. Wenn „DE“ als Sprache konfiguriert ist, wird der Text auf Deutsch vom Widget ausgegeben. Ansonsten auf Englisch.

Die Aktion soll ein Partial View zurückliefern.

public class HelloWorldWidgetController : WidgetControllerBase
{
	public ActionResult Index(string textLanguage)
	{
		HelloWorldWidgetViewModel viewModel = new HelloWorldWidgetViewModel();
		if (string.IsNullOrWhiteSpace(textLanguage))
			viewModel.ErrorText = "No language configured";
		else
			switch (textLanguage.ToUpper())
			{
				case "DE":
					viewModel.SalutationText = "Hallo";
					viewModel.ToSalutate = "Welt";
					break;

				default:
					viewModel.SalutationText = "Hello";
					viewModel.ToSalutate = "world";
					break;
			}

		return PartialView(viewModel);
	}
}

View

Die View (/Views/HelloWorldWidget/Index.cshtml) für das HelloWorldWidget zeigt den Inhalt nur wenn kein Fehler auftritt. Der Fehlertext befindet sich in dem data-errortext Attribut.

@model BA.Core.Models.HelloWorldWidgetViewModel
<div class="hello-world-content" data-errortext="@Model.ErrorText">
	@if (string.IsNullOrWhiteSpace(Model.ErrorText))
	{
		<span>@Model.SalutationText</span> <span>@Model.ToSalutate</span>
	}
</div>

Um die Ausrichtungen optisch ansprechend umzusetzen, sollte man enstprechende eigenen CSS.Styles anlegen. In diesem Beispiel werden die Klassen benutzt, um die gewünmschten Ausrichtungen zu erzeugen. Jeder Fall wird aber durch die Anforderungen erheblich unterschiedlich sein. Für dieses Beispiel wird folgendes CSS benutzt:

.hello-world .widget-content { position: relative; }
.hello-world .hello-world-content { position: absolute; width: fit-content; }
.hello-world.horizontalAlignRight .hello-world-content { right: 0; }
.hello-world.horizontalAlignCenter .hello-world-content { right: 0; left: 0; margin: auto; }
.hello-world.verticalAlignMiddle .hello-world-content { top: 41%; }
.hello-world.verticalAlignBottom .hello-world-content { bottom: 0 }
.hello-world.bold-text .hello-world-content { font-weight: bolder; }
.hello-world.regular-text .hello-world-content { font-weight: normal; }

UI Script

Die TypeScript Klasse wird bei der Erstellung des Widgets im Browser benutzt. Das HelloWorldWidget überschreibt die OnContentLoaded Funktion, um einen möglichen Fehler zu behandeln.

module BA.Ui.Widgets {
	"use strict";
	export class HelloWorldWidget extends Widget {
		public override OnContentLoaded(): void {
			let errorText: string = $(this.GetWidgetJQIdSelector() + " .hello-world-content").data("errortext");

			if (errorText && errorText != "")
				this.SetWidgetState(WidgetState.ContentError, true, errorText, false);
		}
	}
}

Ergebniss

Jetzt kann das Widget in einer Seite konfiguriert werden. Als Beispiel werden zwei konfiguriert: Eins mit fehlender Sprache und eins auf Deutsch