Skip to content

A form handling library inspired by Inertia.js useForm, with Axios integration and Laravel validation support

Notifications You must be signed in to change notification settings

isap-ou/axios-form-handler

Repository files navigation

axios-form-handler

A form handling library inspired by Inertia.js useForm, with Axios integration for seamless API requests and Laravel validation support.

Features

  • 🚀 Inertia.js-like API: Familiar useForm interface for developers coming from Inertia.js
  • 🔧 TypeScript Support: Full TypeScript support with type definitions
  • 🌐 Axios Integration: Built-in HTTP client integration
  • Laravel Validation: Automatic Laravel validation error handling (422 responses)
  • 🔄 State Management: Built-in form state management (processing, errors, fields)
  • 📦 Framework Agnostic: Works with React, Vue, Alpine.js, or vanilla JS/TS
  • 🎯 Lightweight: Minimal dependencies, maximum functionality

Installation

npm install axios-form-handler
yarn add axios-form-handler
pnpm add axios-form-handler

Why axios-form-handler?

If you love the simplicity of Inertia.js useForm but need to use it with traditional APIs or in non-Inertia applications, this library is for you! It provides the same intuitive form handling experience with:

  • Laravel-ready: Automatically handles Laravel validation responses (422 status codes)
  • Familiar API: Same method names and behavior as Inertia.js useForm
  • Universal compatibility: Works in any JavaScript/TypeScript environment
  • Axios powered: Leverages the popular Axios HTTP client

Perfect for developers building SPAs or Alpine.js with Laravel backends, migrating from Inertia.js, or anyone who wants Laravel-style form validation in their frontend applications.

Quick Start

import { useForm } from 'axios-form-handler';

// Create a form instance (just like Inertia.js!)
const form = useForm({
  name: '',
  email: '',
  message: ''
});

// Submit the form to your Laravel API
form.post('/api/contact', {
  onSuccess: (data) => {
    console.log('Form submitted successfully:', data);
  },
  onValidationErrors: (errors) => {
    // Laravel validation errors automatically parsed
    console.log('Validation errors:', errors);
  },
  onError: (error) => {
    console.log('Request failed:', error);
  }
});

Laravel Backend Integration

This library is designed to work seamlessly with Laravel's validation system:

// Laravel Controller
public function store(Request $request)
{
    $request->validate([
        'name' => 'required|string|max:255',
        'email' => 'required|email',
        'message' => 'required|string'
    ]);
    
    // Your logic here...
    
    return response()->json(['message' => 'Success!']);
}

When validation fails, Laravel returns a 422 status code with errors in this format:

{
    "errors": {
        "email": ["The email field is required."],
        "name": ["The name field is required."]
    }
}

The library automatically catches these errors and populates the form.errors object!

API Reference

useForm(fields)

Creates a new form instance with the specified fields.

Parameters:

  • fields (Record<string, any>): Initial form field values

Returns: FormInstance

Form Methods

post(route, options?)

Submit form data via POST request.

put(route, options?)

Submit form data via PUT request.

patch(route, options?)

Submit form data via PATCH request.

delete(route, options?)

Submit form data via DELETE request.

reset()

Reset form to initial values and clear errors.

clearErrors()

Clear all validation errors.

setError(key, message)

Set validation error for a specific field.

Response Options

interface ResponseOption {
  onSuccess?: (data: Record<any, any>) => void;
  onValidationErrors?: (data: Record<any, any>) => void;
  onError?: (error: AxiosError) => void;
  onFinish?: () => void;
}

Form Properties

  • fields: Access to all form field values
  • errors: Current validation errors
  • processing: Boolean indicating if request is in progress
  • hasErrors: Boolean indicating if form has validation errors

Advanced Usage

Custom Axios Instance

import axios from 'axios';
import { setFormAxios } from 'axios-form-handler';

// Create custom axios instance
const api = axios.create({
  baseURL: 'https://api.example.com',
  headers: {
    'Authorization': 'Bearer your-token'
  }
});

// Set as default for all forms
setFormAxios(api);

Working with Form Fields

const form = useForm({
  username: 'john_doe',
  email: 'john@example.com'
});

// Access field values
console.log(form.username); // 'john_doe'
console.log(form.fields); // { username: 'john_doe', email: 'john@example.com' }

// Update field values
form.username = 'jane_doe';
form.email = 'jane@example.com';

// Check for errors
if (form.hasErrors) {
  console.log(form.errors);
}

Laravel Validation Error Handling

The library automatically handles Laravel-style validation errors (422 status code) exactly like Inertia.js:

const form = useForm({ 
  email: '', 
  password: '' 
});

form.post('/api/login', {
  onValidationErrors: (errors) => {
    // Laravel validation errors are automatically parsed
    console.log(errors.email);    // "The email field is required"
    console.log(errors.password); // "The password field is required"
  }
});

// Access errors directly on the form object
if (form.hasErrors) {
  console.log(form.errors.email); // Direct access to field errors
}

Laravel Response Format (422 status):

{
  "message": "The given data was invalid.",
  "errors": {
    "email": ["The email field is required."],
    "password": ["The password must be at least 8 characters."]
  }
}

Parsed Form Errors:

form.errors = {
  email: "The email field is required.",
  password: "The password must be at least 8 characters."
}

Loading States

const form = useForm({ name: '', email: '' });

form.post('/api/contact', {
  onFinish: () => {
    // This runs whether the request succeeds or fails
    console.log('Request completed');
  }
});

// Check processing state
if (form.processing) {
  console.log('Form is being submitted...');
}

Migration from Inertia.js

If you're migrating from Inertia.js or want to use the same patterns, the API is nearly identical:

Inertia.js

import { useForm } from '@inertiajs/react'

const form = useForm({
  name: '',
  email: '',
})

form.post('/users', {
  onSuccess: () => alert('Success!'),
})

axios-form-handler

import { useForm } from 'axios-form-handler'

const form = useForm({
  name: '',
  email: '',
})

form.post('/api/contact', {
  onSuccess: () => alert('Success!'),
})

The main differences:

  • Add /api prefix to your routes (or configure Axios base URL)
  • Import from axios-form-handler instead of @inertiajs/react
  • Optionally configure custom Axios instance for authentication

Alpine.js integration

import Alpine from 'alpinejs';
import axios from 'axios';
import { setFormAxios, useForm } from 'axios-form-handler';

axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
axios.defaults.headers.common['X-CSRF-Token'] = document.querySelector('meta[name="csrf_token"]').getAttribute('content');

setFormAxios(axios);

document.addEventListener('alpine:init', () => {
    Alpine.data('form', (route) => ({
        route,

        init() {
            this.form = useForm({
                first_name: '',
                last_name: '',
                email: '',
            });
        },

        onSubmit() {
            this.form.post(route, {
                onSuccess: (data) => {
                    alert('Message sent successfully!');
                    form.reset();
                },
            });
        },
    }));
});
<div x-data="form('/api/register')">
    <form @submit="onSubmit">
        <div class="grid grid-cols-2 gap-4">
            <div class="col-span-1 space-y-1.5">
                <label for="first_name">First name</label>
                <input type="text" x-model="form.first_name" />
                <template x-if="form.errors?.first_name">
                    <div class="text-red-600 text-sm" x-text="form.errors?.first_name"></div>
                </template>
            </div>
            <div class="col-span-1 space-y-1.5">
                <label for="last_name">Last name</label>
                <input type="text" x-model="form.last_name" />
                <template x-if="form.errors?.last_name">
                    <div class="text-red-600 text-sm" x-text="form.errors?.last_name"></div>
                </template>
            </div>
            <div class="col-span-2 space-y-1.5">
                <label for="email">E-mail</label>
                <input type="email" x-model="form.email" />
                <template x-if="form.errors?.email">
                    <div class="text-red-600 text-sm" x-text="form.errors?.email"></div>
                </template>
            </div>
            <div class="col-span-2 text-right">
                <button type="submit">Submit</button>
            </div>
        </div>
    </form>
</div>

Contributing

Please, submit bugs or feature requests via the Github issues.

Pull requests are welcomed!

Thanks!

License

This project is open-sourced software licensed under the MIT License.

You are free to use, modify, and distribute it in your projects, as long as you comply with the terms of the license.


Maintained by ISAPP and ISAP OÜ.
Check out our software development services at isap.me.

About

A form handling library inspired by Inertia.js useForm, with Axios integration and Laravel validation support

Resources

Stars

Watchers

Forks

Packages

No packages published