Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Il Local State in Alpine.js: la direttiva x-data

Alpine.js: parliamo dello Stato, l'insieme dei dati che determinano il comportamento e l'aspetto di un componente di Alpine
Alpine.js: parliamo dello Stato, l'insieme dei dati che determinano il comportamento e l'aspetto di un componente di Alpine
Link copiato negli appunti

Lo Stato è l'insieme dei dati che determinano il comportamento e l'aspetto di un componente di Alpine.js. In pratica, lo Stato è costituito dall'insieme delle variabili che memorizzano informazioni che cambiano in modo reattivo con l'interazione dell'utente. Ogni volta che l'utente esegue operazioni che cambiano lo stato, Alpine.js aggiorna automaticamente il DOM.

È possibile rendere disponibili i dati a livello locale o globale. Si parla così di local state e global store. I dati disponibili a livello locale sono accessibili solo all'interno di una determinata sezione di HTML (un componente Alpine) e non influenzano altre parti della pagina. Per fornire dati locali ad un blocco HTML si usa la direttiva x-data. Vediamo come accedere ai dati a livello locale con degli esempi pratici.

Il local state di Alpine.js

Alpine.js consente di dichiarare lo stato di un blocco HTML in un singolo attributo x-data. La documentazione recita testualmente:

Everything in Alpine starts with the x-data directive.

Con l'attributo x-data, un frammento di HTML definisce un componente Alpine. Ecco un esempio:

<div x-data="{ count: 0 }">
	<button x-on:click="count++">Increment</button>
	<span x-text="count"></span>
</div>

Nell'esempio qui sopra,

  • x-data indica ad Alpine.js che la div e tutti gli elementi contenuti costituiscono un componente Alpine;
  • { count: 0 } definisce un oggetto JSON che rappresenta lo stato iniziale del componente. In questo caso abbiamo solo la proprietà count che viene inizializzata a 0.

La direttiva x-data fornisce, quindi, i dati reattivi a cui il componente deve fare riferimento, definiti come proprietà di un oggetto JavaScript. Le proprietà così definite sono disponibili a tutti gli elementi contenuti nel componente Alpine.

In quest'altro esempio, la proprietà today contiene una "arrow function":

<div x-data="{ today: () => new Date().toLocaleDateString() }">
	<span x-text="today()"></span>
</div>

x-data viene valutato come un normale oggetto JavaScript. In quanto tale, oltre alle normali proprietà, può contenere metodi e getter. Nell'esempio che segue, il metodo toggle viene eseguito ogni volta che un utente fa clic sul pulsante:

<div x-data="{ show: false, toggle() { this.show = ! this.show } }">
	<button @click="toggle()">Toggle</button>
	<div x-show="show" x-transition.duration.500ms>
		Hello 👋
	</div>
</div>

Si noti che abbiamo utilizzato this per accedere allo stato sullo stesso oggetto.

Infine, quando l'unico scopo è quello di restituire dati derivati da altre proprietà dello stato, possiamo utilizzare una funzione che si comporta in modo simile ad un getter.

<div x-data="{
	firstName: 'Mario',
	lastName: 'Rossi',
	get fullName() { return `${this.firstName} ${this.lastName}`; }
}">
	<p>Nome completo: <span x-text="fullName"></span></p>
</div>

get fullName() definisce la proprietà fullName, il cui valore è una funzione. La funzione restituisce la stringa risultante dalla concatenazione dei valori delle proprietà firstName e lastName, a cui accede tramite la keyword this.

La funzione, inoltre, aggiorna il valore calcolato ogni volta che questo viene modificato. Ad esempio, potremmo aggiungere due campi per permettere all'utente di cambiare il nome predefinito:

<div x-data="{
	firstName: 'Mario',
	lastName: 'Rossi',
	get fullName() { return `${this.firstName} ${this.lastName}`; }
}">
	<p>Nome completo: <span x-text="fullName"></span></p>
	<input type="text" x-model="firstName" placeholder="Nome">
	<input type="text" x-model="lastName" placeholder="Cognome">
</div>

La direttiva x-model aggancia il valore del campo di testo alle corrispondenti proprietà di x-data. In questo modo i dati cambiano in modo interattivo all'input dell'utente.

Negli esempi precedenti, abbiamo sempre utilizzato x-data con una div. Quando un componente contiene un solo elemento è possibile assegnare la direttiva x-data a quell'unico elemento, senza utilizzare un elemento contenitore.

<button x-data="{ count: 0 }" x-on:click="count++" x-text="`Hai cliccato ${count} volte`"></button>

La proprietà Alpine.data

Alpine.data è una proprietà di Alpine.js che permette di spostare logica e dati dall'attributo x-data ad un template esterno in modo che possano essere riutilizzati. Potremmo, ad esempio, modificare il codice dell'esempio precedente come segue:

<script>
	document.addEventListener('alpine:init', () => {
		Alpine.data('persona', () => ({
			firstName: 'Mario',
			lastName: 'Rossi',
			fullName() {
				return `${this.firstName} ${this.lastName}`;
			}
		}));
	});
</script>
<div x-data="persona">
	<p>Nome completo: <span x-text="fullName"></span></p>
	<input type="text" x-model="firstName" placeholder="Nome">
	<input type="text" x-model="lastName" placeholder="Cognome">
</div>

In questo esempio abbiamo fatto riferimento al provider di Alpine.js con il nome persona. È possibile anche invocare il provider con persona() in modo da instanziare il componente con i parametri specificati. Ad esempio:

<script>
	document.addEventListener('alpine:init', () => {
		Alpine.data('persona', (name, surname) => ({
			firstName: name,
			lastName: surname,
			fullName() {
				return `${this.firstName} ${this.lastName}`;
			}
		}));
	});
</script>
<div x-data="persona('Roberto', 'Bianchi')">
	<p>Nome completo: <span x-text="fullName"></span></p>
	<input type="text" x-model="firstName" placeholder="Nome">
	<input type="text" x-model="lastName" placeholder="Cognome">
</div>
<div x-data="persona('Giuseppe', 'Verdi')">
	<p>Nome completo: <span x-text="fullName"></span></p>
	<input type="text" x-model="firstName" placeholder="Nome">
	<input type="text" x-model="lastName" placeholder="Cognome">
</div>

In questo esempio document.addEventListener('alpine:init', () => { ... }); aggiunge un event listener che dice al browser di ascoltare l'evento alpine:init. Questo evento viene emesso da Alpine.js quando la libreria è stata completamente caricata e inizializzata, ma prima che Alpine inizi a cercare e inizializzare i componenti nella pagina. In questo modo, l'oggetto Alpine.data sarà disponibile prima che Alpine cominci a lavorare sul DOM. Si noti che alpine:init viene eseguito una sola volta.

Ora possiamo riutilizzare l'oggetto persona più volte nella stessa pagina, passando ogni volta parametri diversi.

Ti consigliamo anche