Alpine
Alpine adds behaviour to HTML with attributes - and PAD writes that HTML. Both use braces, and PAD reads every { of a template as the start of a tag, so the state of a component comes from the page's PHP as JSON instead:
<div x-data="{^profile}"> <!-- $profile = [ 'name' => 'Ada', 'likes' => 12 ] -->
<h2 x-text="name"></h2>
<button @click="likes++">♥ <span x-text="likes"></span></button>
</div>
The ^ sigil writes a field as JSON escaped for the attribute: a quote or a brace in a value stays text. Three ways keep the braces apart:
-
State from PHP -
x-data="{^field}", as above. -
Components in a file -
Alpine.data('tabs', list => (...))in a script ofwww/, called by name with PAD's data:x-data="tabs({^tabs})". Load the page's scripts before Alpine, and Alpine withdefer. -
A space after the brace -
{ open: false }is no PAD tag; fine for a short object.
Talking back
A component asks the page that wrote it: ?page&padFormat=json answers what the page's PHP names in $padExpose (Data answers). A post carries the session's token in an X-CSRF-Token header, read from <meta name="csrf-token" content="{csrf token}">. A form's rules can live in PHP for both sides - padValidateClient ( $rules ) for the browser, padValidate ( $rules ) for the post (Client validation) - and padSse() streams events an EventSource in x-init turns into state (Server sent events).
The Alpine application shows each of these, with its template, PHP and script: alpine.