3D-Grafik von Pawel Czerwinski – https://unsplash.com/@pawel_czerwinski

Temporäres und persistentes State Management mit Alpine.js

In diesem Beitrag erfährst du, wie du mit Alpine.js sowohl temporäre als auch persistente States verwalten kannst und wie du damit deine User Experience optimieren kannst.

Jairus Joer

Jairus Joer

Die Texte in diesem Artikel wurden teilweise mit Hilfe künstlicher Intelligenz erarbeitet und von uns korrigiert und überarbeitet. Für die Generierung wurden folgende Dienste verwendet:

In unserem ersten Beitrag zur Verwendung von Alpine.js in einer Produktionsumgebung haben wir ein Szenario skizziert, in dem Alpine’s Kontexte verwendet werden können, um sowohl lokale als auch globale Scopes abzubilden, über die Daten bereitgestellt werden können.

Mit diesem Beitrag möchten wir dieses Szenario wieder aufgreifen und vertiefen. In dieser Demonstration werden wir eine Compliance-Lösung für externe Inhalte realisieren und die Entscheidungen der Nutzer:innen temporär oder persistent speichern.


Notwendige Utilities einrichten

Bevor wir mit der Gestaltung der tatsächlichen Komponenten beginnen, benötigen wir eine einfache Funktion, um Daten aus localStorage zu lesen oder Daten dorthin zu schreiben.

local() gibt entweder ein Objekt zurück, das aus dem lokal gespeicherten JSON-Wert des angegebenen key erzeugt wurde, oder ein leeres Objekt, wenn kein Wert für den angegebenen key im lokalen Speicher gefunden wurde.

scripts/utilities.ts
export const local = (key: string, value: any = null): object => {
  if (value != null) localStorage[key] = JSON.stringify(value);
  return localStorage?.[key] ? JSON.parse(localStorage[key]) : {};
};

Aufsetzen des globalen Scopes mit app

Um auf den Zustand der Compliance innerhalb der Applikation zugreifen zu können, konzipieren wir einen neuen Kontext für Alpine: app. Im Kontext von app speichern wir unter compliance das Objekt aus dem lokalen Speicher, beziehungsweise das leere Objekt, insofern der lokale Speicher erstmals konfiguriert werden muss:

Die hier verwendete Methode weicht von unseren vorherigen Beiträgen zu Alpine.js ab und setzt auf einen späteren Import des Kontexts app in einer globalen Skript-Datei.

scripts/alpine/app.ts
import { local } from '../utilities';

export const app = () => ({
  compliance: local('compliance'),
});

Unseren Kontext app registrieren wir anschließend für ein Element, dass alle späteren Implementierungen der Compliance umfassen wird:

index.html
<html x-data="app">...</html>

In unserem Beispiel registrieren wir unseren globalen Kontext über das Element <html>, wobei aber auch <body> oder Root-Elemente für Apps wie <div id="root"> verwendet werden können.


Aufbau der Compliance

Jetzt, wo wir die nötigen Vorbereitungen für den lokalen Speicher und den globalen Scope abgeschlossen haben, können wir mit der tatsächlichen Implementierungen der Compliance beginnen:

Im neuen Kontext compliance deklarieren wir die Methode toggle() mit dem Parameter type, über die wir die Zustimmung der Nutzer:innen zukünftig erfassen wollen.

Unsere vorab deklarierte Methode local() hilft uns hierbei - sofern die Präferenz der Nutzer:innen nicht 'single', also temporär ist - die erfassten Daten in Form eines Objektes im lokalen Speicher festzuhalten.

scripts/alpine/compliance.ts
import { local } from "../utilities";

export const compliance = (type: string) => ({
  toggle(preference: string) {
    if (preference == 'single') return (this.compliance[type] = !this.compliance?.[type]);
      this.compliance[type] = !this.compliance?.[type];
      local("compliance", this.compliance);
    },
});

Das entsprechende HTML-Snippet, das in der Anwendung platziert wird, kann wie folgt aussehen und besteht im Wesentlichen aus zwei Abschnitten:

  • dem Nutzerdialog zur Zustimmung, gesteuert durch x-show="!compliance?.youtube"
  • und dem Inhalt in Form eines Iframes, dessen externer Inhalt durch x-bind gesteuert wird
Compliance Snippet
<div x-data="compliance('youtube')">
  <div x-show="!compliance?.youtube" x-transition>
    <p>...</p>

    <button x-on:click="toggle('single')">...<button>
    <button x-on:click="toggle('always')">...<button>
  </div>

  <iframe frameborder="0" x-bind:src="compliance?.youtube && 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'" x-show="compliance?.youtube" x-transition></iframe>

  <button x-show="compliance?.youtube" x-on:click="toggle('always')">...</button>
</div>

Indexierung der Komponenten

Um den Zugriff auf die deklarierten Methoden zu vereinfachen, erstellen wir eine index.ts im Alpine-Verzeichnis und exportieren die zuvor erstellten Dateien.

scripts/alpine/index.ts
export {app} from './app';
export {compliance} from './compliance';

Integration

Für die Integration unseres neuen Compliance Snippets importieren wir einfach Alpine.js und unsere Methoden für Alpine und registrieren diese im Callback des addEventListener für alpine:init.

scripts/globals.ts
import Alpine from 'alpinejs';
import { app, compliance } from './alpine';

document.addEventListener('alpine:init', () => {
  Alpine.data('app', app);
  Alpine.data('compliance', compliance);
});

Alpine.start();

Schließlich importieren wir das kompilierte Skript als Modul in unser Projekt:

index.html
<body>
  ...
  <script src="scripts/globals.js" type="module"></script>
</body>

TL;DR

Alpine.js kann verwendet werden, um temporäre und persistente States zu verwalten, um eine Compliance-Lösung für externe Inhalte zu realisieren.