Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Advanced forms with Alpine.js
Aggregata profile imageJairus Joer
Jairus Joer forAggregata

Posted on • Edited on • Originally published ataggregata.de

Advanced forms with Alpine.js

The texts in this article were generated in parts by ChatGPT and DeepL Write and corrected and revised by us.

If you are not yet familiar with working on forms with Alpine.js, you can refresh your knowledge in our first article on this topic,Interactive forms with Alpine.js.

In our first article on interactive forms with Alpine.js, we already indicated that Alpine.js can also be used to influence individual elements in addition to the general display of server-side information in the form.

Due to the popular demand, we have decided to take up precisely this topic in this follow-up article and show examples of how you can use information and states to validate a form with Alpine.js.

Setup

For this demonstration, we are using ourAstro Boilerplate,
which we have already presented in detail in anearlier article.

If our boilerplate isn't right for you, that's not a problem. The steps for validating form entries work in any project with Alpine.js.

Integrating methods for Alpine.js

In order to be able to access the required data and methods from Alpine.js in the further course of the implementation, these are first declared in order to avoid errors in the further course.

form.ts

form() controls theloading state and saves theResponse sent by the server via thesubmit() method, which is executed when the form is submitted.

A fictitiousfakeResponse() is also included, which "receives" exemplary and simplified validation errors from our fictitious backend.

import{sleep}from"../utilities";exportconstform=()=>({loading:false,response:nullasunknown,asyncsubmit(event:SubmitEvent){this.loading=true;this.response=null;constformData=newFormData(event.targetasHTMLFormElement);/**     * Replace the following fake response with your `fetch` request and     * receive the validated results from the server side as JSON.     *     * Make sure you add the necessary attributes to the `<Input />'     * elements to perform client-side validation as well.     */constfakeResponse=async()=>{awaitsleep(1000);// Mock response timereturn{errors:{// [input.name]: "message string"username:"Username is alrady taken",password:"Password is too short",},};};this.response=awaitfakeResponse();this.loading=false;},});
Enter fullscreen modeExit fullscreen mode

TheResponse must contain anerror object in which each key-value pair consists of the name of the input element and the associated validation error.

input.ts

input.ts handles the display of validation errors for an input element via thevalidate() method, which is integrated via thex-effect attribute in order to recalculate the data for display when the form is submitted.

exportconstinput=()=>({error:nullasunknown,validate(){if(!this.response?.errors?.[this.$el.name])return(this.error=null);this.error=this.response.errors[this.$el.name];},});
Enter fullscreen modeExit fullscreen mode

globals.ts

Finally, the methods declared for Alpine.js are imported for this step and registered in the EventListeneralpine:init in order to be able to access the required scopes.

importAlpinefrom"alpinejs";import{app}from"./alpine/app";import{form}from"./alpine/form";import{input}from"./alpine/input";// Await Alpine.js initializationdocument.addEventListener("alpine:init",()=>{Alpine.data("app",app);Alpine.data("form",form);Alpine.data("input",input);});Alpine.start();
Enter fullscreen modeExit fullscreen mode

Declaring optional utility methods

So that we can also use names for input elements as labels, we create the methodcapitalize, which splits strings written in kebab-case (e.g.:"email-address") and capitalises each word.

If you decide against capitalisation, the corresponding references in theinput.astro component must be removed

exportconstcapitalize=(string:string)=>{returnstring.split("-").map((word)=>word[0].toUpperCase()+word.substring(1)).join("");};
Enter fullscreen modeExit fullscreen mode

Creating pages and components in Astro

In the following step, we create the pages and components we need for the form. We define an<Input /> component and integrate it into the form block.

input.astro

input.astro combines the elements<input /> and<label> in one component and also contains the representation of the validation errors, which are mapped via the Alpine contextinput.

---import { capitalize } from "@/scripts/utilities"const { name, ...props } = Astro.props---<div   x-data="input">  <div       x-bind:class="error && 'text-rose-500'"  >    <label           for={name}      title={capitalize(name)}    >      {capitalize(name)}{props?.required && '*'}    </label>    <div           x-cloak      x-show="error"      x-transition    >      <span               x-text="error"      ></span>    </div>  </div>  <input       x-bind:class="error && 'border-rose-500'"    {name}    {...props}    x-effect="validate"  /></div>
Enter fullscreen modeExit fullscreen mode

index.astro

index.astro represents our form block and uses the predefined component<Input /> and supplements its logic with theform context so that errors from theresponse object can be displayed.

While our component<Input /> handles the display of validation errors, we bind thedisabled attribute of the individual input elements to theloading state in order to prevent multiple submissions of the form during processing.

---import Root from "@/layouts/root.astro"import Input from "@/components/input.astro"const meta = {  title: "Advanced forms with Alpine.js"}---<Root {meta}>  <main>    <form           x-data="form"      x-on:submit.prevent="submit"    >      <Input               name="username"        type="email"        required        placeholder="tim@apple.com"        x-bind:disabled="loading"      />      <Input               name="password"        type="password"        required        placeholder="Your password"        x-bind:disabled="loading"      />      <button               type="submit"        x-bind:disabled="loading"      >        Submit      </button>    </form>  </main></Root>
Enter fullscreen modeExit fullscreen mode

TL;DR

With Alpine.js, we demonstrate how validation errors from the backend are dynamically displayed in a form and how input elements react to corresponding events in the browser.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Aggregata is a platform for the web, applications, and machine learning, which discusses current trends and topics.

More fromAggregata

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp