Anwendungsindividueller Browser-Tab-Titel
Der Titel im Browser-Tab (HTML <title>) einer TopLogic-Anwendung kann zur Laufzeit dynamisch gesetzt werden — z.B. abhängig von der aktuell selektierten Entität (Projekt: <Name>), vom umgebenden Tab oder Tile, oder über eine eigene Konfiguration.
Ohne explizite Konfiguration bleibt das Verhalten wie bisher: der Titel wird aus LayoutComponent.getTitleKey() der MainLayout aufgelöst und einmalig beim Initial-Rendering geschrieben.
Bausteine
1. Low-Level-API auf `WindowScope`
{{{#!java /**
- Sets the page title shown in the browser tab and title bar of this window. */
void setPageTitle(String title); }}}
Die Implementierung in BrowserWindowControl puffert den Wert und schickt auf der nächsten Revalidation ein JSSnipplet mit document.title = '...' an den Client. Jedes Browser-Fenster hat seinen eigenen Titel; Hauptfenster (MainLayout) und Zusatzfenster (WindowComponent) verwenden je eine eigene BrowserWindowControl-Instanz, die API funktioniert daher transparent für beide.
Direkte Verwendung ist selten nötig — Anwendungen konfigurieren stattdessen einen der unten beschriebenen Resolver bzw. den globalen Kanal.
2. Globaler `pageTitle`-Kanal am `MainLayout`
Das MainLayout hat einen zusätzlichen, programmatischen Komponentenkanal pageTitle (com.top_logic.layout.channel.PageTitleChannel). Wert-Änderungen werden über MetaLabelProvider in einen String konvertiert und an WindowScope.setPageTitle(...) weitergereicht. Bei null als Kanalwert wird der Default aus getTitleKey() rekonstruiert.
Der Kanal kann nicht über <additional-channel> gebunden werden (programmatische Kanäle sind kollisionsgeschützt). Stattdessen gibt es einen dedizierten <page-title>-Eintrag in MainLayout.Config:
{{{#!xml <mainLayout ...>
<page-title class="com.top_logic.model.search.providers.TransformLinkingByExpression"
input="selection(mainNavigation)"
function="x -> $x == null ? null : $x.get(my.app:Project#name)"/>
...
</mainLayout> }}}
Die Bindung erfolgt über ModelSpec, d.h. der volle TL-Script-Mechanismus inkl. TransformLinkingByExpression steht zur Verfügung.
Einsatzbereich: Anwendungen mit einer einzigen, global gültigen Titelquelle.
3. `PageTitleResolver` — sektionslokaler Titel
In TabComponent-zentrierten Hauptnavigationen reicht ein einziger globaler Titel nicht. Hier kommt com.top_logic.layout.basic.page.PageTitleResolver ins Spiel — ein abstrakter ComponentResolver, der an der Komponente konfiguriert wird, deren Sichtbar-Werden den Titel beanspruchen soll.
Lebenszyklus:
- Beim Resolve registriert der Resolver einen VisibilityListener an der tragenden Komponente.
- Beim Sichtbar-Werden pusht der Resolver den berechneten Titel via MainLayout.getWindowScope().setPageTitle(...).
- Beim Unsichtbar-Werden ruft der Resolver MainLayout.applyDefaultPageTitle() auf, der entweder den aktuellen Wert des pageTitle-Kanals oder — falls dieser null ist — den aus getTitleKey() aufgelösten Default wiederherstellt.
Das funktioniert ohne Eingriff in die TabComponent und ist auch für Tile-basierte Navigation geeignet (siehe TabPageTitle).
Es gibt zwei mitgelieferte Implementierungen:
3a. `DynamicPageTitle` — Titel aus einem Kanal
Für dynamische Titel, die sich aus einem Komponentenkanal speisen (z.B. aktuelle Selektion einer Komponente):
{{{#!xml <component class="...">
<componentResolvers>
<componentResolver class="com.top_logic.layout.basic.page.DynamicPageTitle"
value="selection(self())"/>
</componentResolvers>
</component> }}}
- value ist ein ModelSpec (Pflichtfeld), bei dem TransformLinkingByExpression & Co. zur Anwendung kommen können, um den Quellwert vor der Anzeige zu transformieren — eine separate function-Property gibt es nicht mehr, weil sich Transformationen sauberer als transformierender Kanal modellieren lassen.
- Der Wert wird via MetaLabelProvider in einen Anzeige-String gewandelt.
- Ändert sich der Quellwert während die Komponente sichtbar ist, wird der Titel sofort neu gepusht.
- Ein null-Wert ergibt einen leeren Titel und wird unterdrückt.
3b. `TabPageTitle` — Titel aus dem umgebenden Tab/Tile
Für Sichten, die ihren Titel ohne Konfiguration aus dem umgebenden Navigationskontext beziehen sollen:
{{{#!xml <component class="...">
<componentResolvers>
<componentResolver class="com.top_logic.layout.basic.page.TabPageTitle"/>
</componentResolvers>
</component> }}}
- In einer Tile-basierten Navigation (innerhalb eines RootTileComponent) wird der Titel aus dem Label der aktuell angezeigten Tile-Pfad-Komponente abgeleitet — wie es auch im Tile-Breadcrumb erscheint (RootTileBreadcrumbControlProvider.tileBreadcrumbLabel(...)).
- Andernfalls wird der Titel aus dem Label des umgebenden TabComponent-Tab-Cards genommen.
- Bei Navigation innerhalb eines Tile-Pfads (DISPLAYED_PATH_PROPERTY) wird der Titel automatisch mit dem Breadcrumb mitgeführt.
4. Konfiguration im In-App-Layout-Editor
In der zentralen com.top_logic/contentLayout.template.xml ist eine pageTitle-Property hinzugekommen, sodass der Page-Title-Resolver für jede über den Layout-Editor angelegte Sicht konfigurierbar ist:
{{{#!xml <property name="pageTitle"
instance-type="com.top_logic.layout.basic.page.PageTitleResolver"
type="PolymorphicConfiguration"
/> }}}
Die Property erscheint im Editor als Seiten-Titel / Page title und lässt eine der oben genannten Resolver-Implementierungen auswählen. Wird sie leer gelassen, wird kein Resolver eingebettet und der globale Default bleibt aktiv.
Wie nutzt man das Feature?
Als Anwendungsentwickler hat man drei aufeinander aufbauende Stellschrauben:
- Statischer Titel pro Anwendung: nichts tun, der Titel kommt aus getTitleKey() der MainLayout.
- Globaler dynamischer Titel: <page-title>-Element an die MainLayout hängen, gespeist aus einer beliebigen ModelSpec (typisch: Selektion einer Hauptnavigationskomponente).
- Sektionsspezifischer Titel: componentResolver mit DynamicPageTitle (eigene Quelle) oder TabPageTitle (umgebender Tab/Tile) — entweder direkt im Layout-XML oder bequem über die pageTitle-Property im Layout-Editor.
Resolver an mehreren Komponenten dürfen sich überlagern: in einer Tab-Wechsel-Sequenz wird zuerst der alte Tab unsichtbar (Default wird wiederhergestellt), dann der neue sichtbar (der neue Resolver setzt seinen Titel) — dadurch übernimmt immer der gerade sichtbare Resolver die Titel-Hoheit.
Beispielverwendung in `tl-demo`
In der Demo-App ist DynamicPageTitle an der Strukturen-Sicht (editStructureWithExport.xml) konfiguriert, sodass der Browser-Tab-Titel der Selektion im Strukturen-Tree folgt, solange die Sicht aktiv ist.