HProgressor (ehem. MultiStepConfiguratorComponent)
Ort
hermeneus/resources/js/components/HProgressor.vue
Abhängigkeiten
- hermeneus/resources/js/components/HProgressorStore.js
- hermeneus/resources/js/hermeneus.eventbus/eventbus.js
Technologien
- Vue Composition API
- Pinia (Storeverwaltung)
- Tailwind, PrimeVue
Zweck
- Technische Kapselung mehrschrittiger Konfigurationen
- Einheitliche Oberfläche bei der Erstellung beliebiger Konfgurationen
- Navigation zwischen verschiedenen Konfigurationsschritten
Verwendung
Die Komponente ist ein Wrapper, in den beliebige weitere Komponenten eingesetzt werden können. Der Konfigurator ist von den zugrundeliegenden Komponenten entkoppelt; seine Aufgabe besteht ausschließlich darin, das Hin- und Herschalten zwischen den Konfigurationsschritten zu regeln und den Datenfluss mithilfe eines Stores zu vereinheitlichen.
Der Konfigurator wird wie jede normale Vue Komponente eingebunden; bei der Erstellung werden die gewünschten Konfigurationsschritte (bzw -komponenten) als Array an die prop "steps" übergeben:
<h-progressor :steps="components"/>const components = ref([
{
id: 'select_lernstoff',
position: 0,
component: lernstoffSelectorComponent,
title: 'Lerneinheit auswählen',
description: 'Wählen Sie eine Lerneinheit aus', // optional
customEvents: ['lernstoff-composer__lernstoff-selected'],
},
{
id: 'cursus_settings',
position: 1,
component: cursusSettingsComponent,
title: 'Cursus konfigurieren',
hasNextStepCondition: true, // optional
},
{
id: 'start_cursus',
position: 2,
component: cursusStartComponent,
title: 'Start!',
props: {...}, // optional
isOptional: false, // optional
disabledInBreadcrumbs: true, // optional
labelPreviousStep: 'Zurück', // optional, Standard: 'Vorheriger Schritt'
iconPreviousStep: 'fa-solid fa-arrow-left', // optional, Standard: 'fa-solid fa-caret-left'
labelNextStep: 'Weiter', // optional, Standard: 'Nächster Schritt'
iconNextStep: 'fa-solid fa-arrow-right' // optional, Standard: 'fa-solid fa-caret-right'
}
]
);Struktur der "Step"-Objekte
Die Objekte im Array müssen folgende Struktur aufweisen (andere Properties werden ignoriert):
Verpflichtend:
- id: kann individuell gewählt werden, muss eindeutig sein. UUIDs sind möglich, erschweren aber die spätere Auffindbarkeit des Steps und sind deshalb nicht empfehlenswert. Ist die Property z.B. in disabledInBreadcrumbs (s.u.) gesetzt, muss die ID manuell gesetzt und bekannt sein. Grund: um die Komponente später in den Breadcrumbs wieder zu aktivieren, muss (in einer anderen Komponente) ein Event erzeugt werden, welches die ID des zu aktivierenden Steps als Parameter enthält. Dies ist nicht möglich, wenn die ID erst zur Laufzeit dynamisch erzeugt wird (und damit zur Entwicklungszeit unbekannt ist).
- position: numerisch; gibt die Position der Komponente in den Konfigrationsschritten an. Muss eine positive Zahl und eindeutig sein.
- component: Die Vue-Komponente, die für diesen Konfigurationsschritt angezeigt werden soll.
- title: Anzeigename der Komponente.
Optional (können ausgelassen werden, in diesem Fall werden Defaultwerte benutzt)
customEvents: Namen der Events, die in dieser Komponente erzeugt werden und deren Aktionen der Konfigurator berücksichtigen soll. Das Ergebnis des Events wird im Store hinterlegt und ist so später für andere Komponenten abrufbar - dies dient v.a. der Abwärtskompatibilität: auch bestehende Komponenten, die sich auf den EventBus zum Datenaustausch verlassen, können so im Konfigurator zusammen mit reinen storegestützen Komponenten benutzt werden.
props: Ein Objekt mit props, die dieser Komponente übergeben werden sollen. Als Defaultwerte wird ein Objekt mit der o.g. ID des Stepobjekts gesetzt, um diese innerhalb der Komponente dynamisch verfügbar zu machen. Wenn weitere Props übergeben werden, wird das Standardobjekt mit dem benutzerdefinierten Props-Objekt gemergt; die ID ist also auch in diesem Fall zugänglich.
isOptional (default: true): Step kann ohne Userinteraktion übersprungen werden. Wenn false gesetzt ist, wird der "Weiter"-Button solange deaktiviert (disabled), bis in der Komponente das Event "configComplete" mit der ID des Steps erzeugt wurde. Somit können erforderliche Konfig-Angaben in einem Step erzwungen werden.
disabledInBreadcrumbs (default: false): soll die Komponente in der Breadcrumbs-Leiste des Konfigurators deaktiviert werden? Nutzer können diese Komponente dann nicht mehr direkt anspringen - das kann nützlich sein, wenn ein Konfigurationsschritt zwingend vorherige Schritte (z.B. einen bestimmte Eingabedaten) voraussetzt. Wichtig: wird diese Flag gesetzt, sollte sie in irgendeiner anderen Komponente wieder entfernt werden, um die Breadcrumbs konsistent zu halten. Dies ist über das Verschicken des spezifischen Events 'activateStep' in der eigenbetteten Komponente möglich:
EventBus.$emit('activateStep', stepID)Der Payload des Events ist dabei die ID derjenigen Komponente, die in den Breadcrumbs aktiviert werden soll. Die des zu aktivierenden Steps muss zur Entwicklungszeit bekannt sein, was für Komponenten mit der Property "disabledInBreadcrumbs" die Verwendung generierter IDs ausschließt (s.o.)
description (default: null): Eine Beschreibung des Schritts, die unter dem Schritttitel angezeigt wird, wenn der Schritt aktiv ist, sowie unter der Komponente angezeigt wird.
hasNextStepCondition (default: false): Wenn auf true gesetzt, wird der "Weiter"-Button für diesen Schritt nur aktiviert, wenn die Komponente eine computed Property namens
isInValidStatebereitstellt, die true zurückgibt, oder wenn das Event "configComplete" ausgelöst wurde. Dies ermöglicht eine dynamische Validierung von Eingabefeldern oder anderen Bedingungen.labelPreviousStep (default: 'Vorheriger Schritt'): Text für den "Zurück"-Button.
iconPreviousStep (default: 'fa-solid fa-caret-left'): Icon-Klasse für den "Zurück"-Button.
labelNextStep (default: 'Nächster Schritt'): Text für den "Weiter"-Button.
iconNextStep (default: 'fa-solid fa-caret-right'): Icon-Klasse für den "Weiter"-Button.
Zu beachten ist v.a., dass die ID des Stepobjekts wie erwähnt automatisch in die Props der jeweiligen Komponente übertragen wird. Innerhalb jeder Komponente kann also auch auf dynamisch zur Laufzeit erzeugte IDs zugegriffen werden.
Komponenten-Validierung für Weiter-Button
Eine Komponente kann den "Weiter"-Button auf zwei Arten steuern:
Über das Event
configComplete: Die Komponente kann ein Event mit dem NamenconfigCompleteund der ID des Schritts auslösen, um zu signalisieren, dass der Schritt abgeschlossen ist und der "Weiter"-Button aktiviert werden kann:jsEventBus.$emit('configComplete', this.id);Über die computed Property
isInValidState: Wenn der SchritthasNextStepCondition: truedefiniert hat, kann die Komponente eine computed Property mit dem NamenisInValidStatebereitstellen, die true zurückgibt, wenn der "Weiter"-Button aktiviert werden soll:jscomputed: { isInValidState() { return this.formIsValid; } }
HProgressorStore
Der Store stellt eine State-Eigenschaft namens stepData, sowie eine Setter-Methode setStepData(stepID, stepData) bereit. Lesender Zugriff auf stepData ist von überall her direkt möglich; jedoch kann der State nur über den Setter geschrieben werden! Die Möglichkeit, bestimmte stepData-Objekte zu aktualisieren, ist noch nicht eingebaut, aber geplant.
Hintergrund: stepData ist eine mit der Vue 3 Methode readonly() erzeugte Kopie (Proxy) des eigentlichen State-Objekts, das außerhalb des Stores nicht zugänglich ist.
stepData ist eine Map, wobei der Schlüssel die ID eines Steps sein muss (vgl. oben), der Wert ist beliebig. Die ID muss in den Objekten, mit denen der Konfigurator via "steps"-Props initialisiert wird, enthalten sein! Wird eine nicht enthaltene / unbekannte ID übergeben, führt dies zu einem Fehler und das Setzen wird abgebrochen.
Hintergrund: Bei der Initialisierung des Konfigurators werden alle übergebenen Step-IDs automatisch im Store registriert. Nachträgliches Hinzufügen ist bewusst nicht mehr möglich - der Store soll ausschließlich erwartbare Daten zu den definierten Schritten enthalten.
Breadcrumbs-Navigation
Die HProgressor-Komponente stellt eine Breadcrumbs-Navigation am oberen Rand der Komponente bereit. Diese zeigt alle Schritte an und ermöglicht es dem Benutzer, direkt zu einem bestimmten Schritt zu springen, sofern dieser nicht durch die disabledInBreadcrumbs-Eigenschaft deaktiviert wurde. Die Farbgebung der Breadcrumbs passt sich dynamisch an:
- Aktiver Schritt: Hervorgehobene Darstellung mit Primärfarbe
- Bereits abgeschlossene Schritte: Graue Darstellung
- Noch nicht erreichte Schritte: Hellere Darstellung
- Deaktivierte Schritte: Sehr helle, halb-transparente Darstellung
Optionale Schritte
Schritte können als optional markiert werden, indem die Eigenschaft isOptional: true gesetzt wird. In der Breadcrumbs-Navigation werden optionale Schritte mit einem "OPTIONAL"-Label gekennzeichnet.