Now.js Framework Documentation

Now.js Framework Documentation

FormManager

EN 15 Dec 2025 08:24

FormManager

Overview

FormManager is the form management system in Now.js Framework. It supports validation, auto-submit, and API integration.

When to use:

  • Need form handling
  • Need validation
  • Need AJAX submission
  • Need auto-enhance form elements

Why use it:

  • ✅ Automatic validation
  • ✅ AJAX submission
  • ✅ Loading states
  • ✅ Error display
  • ✅ Auto-enhance elements
  • ✅ Multiple submit handlers

Basic Usage

HTML Declarative

<form data-component="form"
      data-action="/api/users"
      data-method="POST">
  <input type="text" name="name" required>
  <input type="email" name="email" required>
  <button type="submit">Submit</button>
</form>

With Success Redirect

<form data-component="form"
      data-action="/api/users"
      data-success-redirect="/users">
  ...
</form>

With Notification

<form data-component="form"
      data-action="/api/contact"
      data-success-message="Message sent successfully!">
  ...
</form>

Data Attributes

Attribute Description
data-component="form" Initialize form
data-action API endpoint
data-method HTTP method (POST, PUT, PATCH)
data-success-redirect Redirect URL on success
data-success-message Success notification
data-error-message Error notification
data-validate Enable validation
data-confirm Confirmation message

JavaScript API

// Get form instance
const form = FormManager.getInstance(element);

// Submit programmatically
await form.submit();

// Reset form
form.reset();

// Set values
form.setValues({
  name: 'John',
  email: 'john@example.com'
});

// Get values
const data = form.getValues();

// Validate
const isValid = form.validate();

Validation

HTML5 Validation

<input type="text" name="name" required minlength="2" maxlength="50">
<input type="email" name="email" required>
<input type="number" name="age" min="18" max="100">
<input type="url" name="website" pattern="https?://.+">

Custom Validation

<input type="text" name="username"
       data-validate="username"
       data-validate-message="Username must be 3-20 characters">
FormManager.addValidator('username', (value) => {
  return /^[a-zA-Z0-9_]{3,20}$/.test(value);
});

Async Validation

FormManager.addValidator('unique-email', async (value) => {
  const response = await ApiService.get(`/api/check-email?email=${value}`);
  return response.data.available;
});

Events

Event When Triggered Detail
form:submit Form submitted {form, data}
form:success Submission success {form, response}
form:error Submission error {form, error}
form:validate Validation run {form, valid}
form:reset Form reset {form}
document.getElementById('my-form').addEventListener('form:success', (e) => {
  console.log('Form submitted:', e.detail.response);
});

API Reference

FormManager.getInstance(element)

Get form instance

FormManager.submit(element)

Submit form

FormManager.validate(element)

Validate form

Returns: boolean

FormManager.reset(element)

Reset form

FormManager.setValues(element, data)

Set form values

FormManager.getValues(element)

Get form values

Returns: Object

FormManager.addValidator(name, fn)

Add custom validator

Real-World Examples

Contact Form

<form data-component="form"
      data-action="/api/contact"
      data-method="POST"
      data-success-message="Message sent successfully!"
      data-success-reset="true">

  <div class="form-group">
    <label>Name</label>
    <input type="text" name="name" required>
  </div>

  <div class="form-group">
    <label>Email</label>
    <input type="email" name="email" required>
  </div>

  <div class="form-group">
    <label>Message</label>
    <textarea name="message" required minlength="10"></textarea>
  </div>

  <button type="submit">Send</button>
</form>

Edit Form

<form data-component="form"
      data-action="/api/users/{{id}}"
      data-method="PUT"
      data-success-redirect="/users"
      data-confirm="Confirm save?">

  <input type="hidden" name="id" value="{{id}}">
  <input type="text" name="name" value="{{name}}">
  <input type="email" name="email" value="{{email}}">

  <button type="submit">Save</button>
</form>

File Upload

<form data-component="form"
      data-action="/api/upload"
      data-enctype="multipart/form-data">

  <input type="file" name="document"
         accept=".pdf,.doc,.docx"
         required>

  <button type="submit">Upload</button>
</form>

With Custom Handler

const form = document.getElementById('custom-form');

form.addEventListener('form:submit', async (e) => {
  e.preventDefault();

  const formData = FormManager.getValues(form);

  // Custom processing
  formData.processed = true;

  try {
    const response = await ApiService.post('/api/custom', formData);
    NotificationManager.success('Success!');
  } catch (error) {
    NotificationManager.error(error.message);
  }
});

CSS for Validation

/* Invalid field */
.form-group.invalid input,
.form-group.invalid textarea,
.form-group.invalid select {
  border-color: #ef4444;
}

/* Error message */
.form-group .error-message {
  color: #ef4444;
  font-size: 0.875rem;
  margin-top: 4px;
}

/* Valid field */
.form-group.valid input {
  border-color: #22c55e;
}

/* Loading state */
form.loading button[type="submit"] {
  opacity: 0.7;
  pointer-events: none;
}

form.loading button[type="submit"]::after {
  content: ' ⏳';
}

Common Pitfalls

⚠️ 1. Must Have name Attribute

<!-- ❌ Missing name -->
<input type="text" id="username">

<!-- ✅ Has name -->
<input type="text" name="username">

⚠️ 2. Button type

<!-- ❌ Default can submit -->
<button>Click</button>

<!-- ✅ Specify type -->
<button type="submit">Submit</button>
<button type="button">Cancel</button>