Your first Flux form
We will begin with the smallest useful Flux interaction: a form that submits in the background and updates itself with the server-rendered result.
The repository’s first example is a session-backed counter at example/01-counter.php. The page contains a <textarea> outside the form so we can see the difference immediately: a normal page reload would cause the whole page to refresh, losing the state of the textarea - but Flux keeps the page state unchanged.
Start with plain HTML
<form method="post">
<output>0</output>
<button name="do" value="increment">Increment</button>
<button name="do" value="decrement">Decrement</button>
</form>
On the server, we can handle the buttons exactly as we always would. Example 01 stores the count in the session, changes the value, and responds with a redirected full HTML page.
[!IMPORTANT] Flux is built as a standalone library, but the main intention is to be used with PHP.GT/WebEngine - Flux is shipped by default in WebEngine applications. All examples and server-side code use plain PHP, but any language or framework could be used. For more information about how WebEngine takes full advantage of Flux, see https://www.php.gt/docs/webengine/flux/
Add Flux
To make the form submit in the background, we have two options.
Option 1: mark the form as a Flux container
<form method="post" data-flux>
<output>0</output>
<button name="do" value="increment">Increment</button>
<button name="do" value="decrement">Decrement</button>
</form>
On a <form>, bare data-flux tells Flux to listen for submit events on that form. The form is also registered as an update target, so when the server returns the next full HTML document, Flux replaces the current form with the matching form from the response.
This keeps the common case small: if the whole form should refresh after it submits, no extra update directive is needed.
Option 2: mark individual buttons to submit, and mark just the elements to update
<form method="post">
<output data-flux="update">0</output>
<button name="do" value="increment" data-flux>Increment</button>
<button name="do" value="decrement" data-flux>Decrement</button>
</form>
<textarea>Type something into this textarea - the state will be persisted after clicking the increment button above.</textarea>
[!NOTE]
data-fluxis a shorthand attribute on some types of element. On forms,data-fluxconverts the form into a Flux container. On buttons,data-fluxis short fordata-flux="submit"- handling the single button click instead of the whole form submission. On links,data-fluxis short fordata-flux="link"- but we haven’t got to links yet. For more information, see the list of flux attributes.
What the response should look like
Flux expects a complete HTML page in response. We do not need to return state in JSON or anything like that, and we do not need a separate partial render just for the counter element. Remember, we’re just enhancing an already-working server-first application. The server can redirect or render the normal route as usual, and Flux will do the rest.
What changes in the browser
When the button is pressed:
- Flux prevents the browser’s default submit.
- Flux gathers
FormData, including the clicked button name and value. - Flux sends the request using
fetch, in the background (also known as “ajax”). - Flux parses the returned HTML document.
- Flux updates whichever targets we registered on the current page. A form marked with bare
data-fluxis one of those targets by default.
That is why the <textarea> in the example keeps its content: only the Flux target updates, not the whole page.
[!INFO] If the form has an
action, Flux treats the response like navigation and also updates the browser history. If there is noaction, Flux updates in place without pushing a history entry.
[!INFO] While a Flux form submission is in flight, Flux adds the class
flux-form-waitingto both the submitting<form>and the page<body>. If a specific submit button triggered the request, that button also getsflux-button-waitinguntil the request finishes. We can use those classes to dim the interface, show a spinner, or disable pointer interactions in our own CSS.
Our form now submits in the background. Next we will decide exactly what gets replaced when updating part of the page.