An open API service indexing awesome lists of open source software.

https://github.com/thavarshan/formlink

โ›“๏ธโ€๐Ÿ’ฅ The source code of Formlink. A Fullstack TypeScript form handler library.
https://github.com/thavarshan/formlink

form formlink formlinkjs fullstack source source-code typescript typescript-library

Last synced: about 1 year ago
JSON representation

โ›“๏ธโ€๐Ÿ’ฅ The source code of Formlink. A Fullstack TypeScript form handler library.

Awesome Lists containing this project

README

          

[![Formlink](./assets/Banner.png)](https://github.com/Thavarshan/formlink)

# Formlink

[![Latest Version on npm](https://img.shields.io/npm/v/formlink.svg)](https://www.npmjs.com/package/formlink)
[![Test](https://github.com/Thavarshan/formlink/actions/workflows/test.yml/badge.svg)](https://github.com/Thavarshan/formlink/actions/workflows/test.yml)
[![Lint](https://github.com/Thavarshan/formlink/actions/workflows/lint.yml/badge.svg)](https://github.com/Thavarshan/formlink/actions/workflows/lint.yml)
[![Total Downloads](https://img.shields.io/npm/dt/formlink.svg)](https://www.npmjs.com/package/formlink)
[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Formlink is a type-safe form-handling library for Laravel + Vue.js applications. It abstracts away form submissions, file uploads, and validation error handling, offering seamless integration with Laravel and Vue.js applications, inspired by Inertia.js's simplicity.

## Features

- โœจ **Type Safety**: Full TypeScript support with type inference
- ๐Ÿš€ **Zero Configuration**: Works out of the box with Laravel
- ๐Ÿ” **Built-in CSRF Protection**: Automatic CSRF token handling
- ๐Ÿ”„ **Progress Tracking**: Real-time file upload progress
- ๐ŸŽฏ **Smart Error Handling**: Automatic Laravel validation error management
- โšก **Event Hooks**: Rich lifecycle hooks for form submission events
- ๐Ÿ“ฑ **Vue 3 Ready**: Reactive forms with Vue 3 composition API
- ๐Ÿ› ๏ธ **Framework Agnostic**: Can be used with any backend, not limited to Laravel
- ๐Ÿ”€ **HTTP Method Support**: Comprehensive support for all HTTP methods
- ๐Ÿงน **Form Reset & State Management**: Easily reset form data to initial state
- ๐Ÿ”„ **Debounced Submissions**: Support for debounced form submissions

## Quick Start

### Installation

```bash
npm install formlink
# or
yarn add formlink
# or
pnpm add formlink
```

### Basic Usage

```typescript
import { useForm } from 'formlink';

interface ContactForm {
name: string;
email: string;
message: string;
}

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

await form.post('/api/contact');
```

### Complete Example

```vue





{{ form.errors.name }}




{{ form.errors.email }}




{{ form.progress.percentage }}% uploaded



{{ form.processing ? 'Sending...' : 'Send Message' }}

import { useForm } from 'formlink';

interface ContactForm {
name: string;
email: string;
file: File | null;
}

const form = useForm<ContactForm>({
name: '',
email: '',
file: null
});

const handleFile = (e: Event) => {
const file = (e.target as HTMLInputElement).files?.[0];
if (file) {
form.file = file;
}
};

const submit = async () => {
await form.post('/api/contact', {
onBefore: () => {
console.log('Request starting');
},
onProgress: (progress) => {
console.log(`${progress.percentage}% uploaded`);
},
onSuccess: (response) => {
console.log('Submission successful', response.data);
},
onError: (errors) => {
console.log('Validation errors', errors);
},
onFinish: () => {
console.log('Request finished');
}
});
};

```

## Available `FormOptions`

The `FormOptions` object allows you to configure hooks and behaviors for form submissions. Here are the available options:

| Option | Type | Description |
|----------------|----------------------------------------------|-----------------------------------------------------------------------------|
| `resetOnSuccess` | `boolean` | Whether to reset the form to its initial state after a successful submission. |
| `onBefore` | `() => void` | Hook that is called before the form submission begins. |
| `onSuccess` | `(response: AxiosResponse) => void` | Hook that is called when the form submission is successful. |
| `onCanceled` | `() => void` | Hook that is called when the form submission is canceled. |
| `onError` | `(errors: Partial>)` | Hook that is called when validation errors occur (e.g., from a Laravel backend). |
| `onFinish` | `() => void` | Hook that is called when the form submission finishes, whether successful or not. |
| `onProgress` | `(progress: Progress) => void` | Hook that tracks file upload progress or long-running requests. |

### Example of Form Options

```typescript
await form.post('/api/contact', {
resetOnSuccess: true,
onBefore: () => console.log('Submitting...'),
onSuccess: (response) => console.log('Submitted', response.data),
onError: (errors) => console.error('Validation errors:', errors),
onFinish: () => console.log('Request finished'),
onProgress: (progress) => console.log(`Upload ${progress.percentage}% complete`),
});
```

## Advanced Features

### Form States

Formlink provides various reactive states:

```typescript
form.processing; // Is the form being submitted?
form.progress; // Upload progress data
form.errors; // Validation errors
form.isDirty; // Has the form been modified?
form.wasSuccessful; // Was the form submission successful?
form.recentlySuccessful; // Was the form submission successful recently?
```

### HTTP Methods

Formlink supports multiple HTTP methods:

```typescript
form.get(url); // GET request
form.post(url); // POST request
form.put(url); // PUT request
form.patch(url); // PATCH request
form.delete(url); // DELETE request
form.options(url); // OPTIONS request
```

### Data Transformation

You can transform form data before it is submitted:

```typescript
form.transform((data) => ({
...data,
name: data.name.trim().toLowerCase()
}));
```

### Error Handling

Set or clear errors manually:

```typescript
// Set a single error
form.setError('email', 'Invalid email format');

// Set multiple errors at once
form.setErrors({
email: 'Invalid email format',
name: 'Name is required',
formError: 'Please fix the errors before submitting'
});

// Clear all errors
form.clearErrors();
```

### Reset Functionality

Reset the form data to its initial state:

```typescript
// Reset all fields
form.reset();

// Reset specific fields
form.reset('email', 'name');
```

### Default Values

Set new default values for the form:

```typescript
// Set all current data as new defaults
form.setDefaults();

// Set a specific field's default value
form.setDefaults('email', 'default@example.com');

// Set multiple field defaults at once
form.setDefaults({
name: 'John Doe',
email: 'john@example.com'
});
```

### Validation

Formlink provides a simple validation system:

```typescript
// Define validation rules
form.rules = {
email: [
{ validate: (value) => !!value, message: 'Email is required' },
{ validate: (value) => /\S+@\S+\.\S+/.test(value as string), message: 'Invalid email format' }
],
name: [
{ validate: (value) => !!value, message: 'Name is required' }
]
};

// Run validation
const isValid = await form.validate();
if (isValid) {
await form.post('/api/contact');
}
```

### Debounced Submissions

For search forms or auto-save functionality:

```typescript
// Debounce form submission (default 300ms)
form.submitDebounced('get', '/api/search');

// Custom debounce time (1000ms)
form.submitDebounced('post', '/api/auto-save', {}, 1000);
```

### Cancellation

Cancel an ongoing form submission:

```typescript
// Start submission
const submissionPromise = form.post('/api/upload-large-file');

// Cancel it if needed
form.cancel();
```

### Custom Axios Instance

You can use a custom Axios instance for your form requests:

```typescript
import axios from 'axios';

const customAxios = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
headers: {
'X-Custom-Header': 'value'
}
});

const form = useForm(data, customAxios);
```

### Resource Cleanup

For single-page applications, ensure proper cleanup:

```typescript
// In your component's onUnmounted lifecycle hook
onUnmounted(() => {
form.dispose();
});
```

## Contributing

Contributions are welcome! See our [Contributing Guide](https://github.com/Thavarshan/formlink/blob/main/.github/CONTRIBUTING.md) for details.

To get started:

1. Fork the repository.
2. Create your feature branch (`git checkout -b feature/your-feature`).
3. Commit your changes (`git commit -m 'Add feature'`).
4. Push to your branch (`git push origin feature/your-feature`).
5. Open a pull request.

### Development Setup

```bash
# Clone the repository
git clone https://github.com/Thavarshan/formlink.git

# Install dependencies
npm install

# Run tests
npm test

# Build the package
npm run build
```

## License

Formlink is open-sourced software licensed under the [MIT license](LICENSE.md).

## Acknowledgments

Special thanks to [**Jonathan Reinink**](https://github.com/reinink) for his work on [**InertiaJS**](https://inertiajs.com/), which inspired this project.