# Forms & Validation

## <mark style="color:red;">Forms in Account Pages​</mark> <a href="#forms-in-account-pages" id="forms-in-account-pages"></a>

```
<pz-form class="js-change-email-form a-ce-form" service="User" action="changeEmail">
  <pz-label>
    {{ _('New email address') }}*
    <pz-input
      type="email"
      name="email"
      w-full
      v-required
      v-email>
    </pz-input>
  </pz-label>
 
  <pz-label>
    {{ _('Re-enter your new email address') }}*
    <pz-input
      type="email"
      name="email_repeat"
      w-full
      v-required
      v-email>
    </pz-input>
  </pz-label>
 
  <pz-label>
    {{ _('Your password') }}*
    <pz-input
      type="password"
      name="password"
      w-full
      v-required>
    </pz-input>
  </pz-label>
 
  <pz-button type="submit" size="lg">
    {{ _('Change Email Address') }}
  </pz-button>
</pz-form>
```

As you can see in the example above, forms are almost completely made via web components. Here, `pz-form` component is responsible for submitting the form. The `service` and `action` attribute allows you to set where you want this form to be submitted to.

Some key points in the example above are:

Every form element inside `pz-form` is also a web component, such as `pz-input`, `pz-label`, `pz-button`. This is required for proper styling of said elements as well as proper validations of them.

All inputs have a `name` attribute, which corresponds to the field name expected by the backend, as well as the `action` you set on `pz-form`. In other words, you can’t submit an input with a name that isn’t included in `pz-form`’s `action`. Similarly, your form won’t work if you use an incorrect name field on the inputs.

PzForm has a unique, `js-` prefixed class or id.

## <mark style="color:red;">Validations</mark>​ <a href="#validations" id="validations"></a>

As seen in the example, all validations are controlled via attributes on input fields directly. Before the form is submitted, PzForm component will trigger these validations.

Please refer to each input component's own documentation for more information about available validations.

## <mark style="color:red;">PzForm Actions​</mark> <a href="#pzform-actions" id="pzform-actions"></a>

PzForm’s result actions are easily configurable via JS:

```

this.form.beforeAction = () => {
  if (this.email.value !== this.emailRepeat.value) {
    this.errorEl.innerHTML = gettext('Email values must be matching.');
    this.errorEl.removeAttribute('hidden');
    return false;
  }
 
  this.errorEl.innerHTML = '';
  this.errorEl.setAttribute('hidden', 'hidden');
};
 
this.form.addEventListener('action-success', () => {
  window.scrollTo({ top: 0, behavior: 'smooth' });
  $(this.form).fadeOut();
  $(this.successHtml).fadeIn();
});
 
this.form.addEventListener('action-error', (error) => {
  const errorDetail = error.detail.error;
 
  if (errorDetail.data?.non_field_errors?.[0]) {
    this.errorEl.innerHTML = errorDetail.data.non_field_errors[0];
    this.errorEl.removeAttribute('hidden');
  }
});
 
```

After selecting the form element (this.form in example above), you can attach a custom `beforeAction` function to it. As the name implies, this allows you to run certain functionality before the form is submitted. In the example above, we are checking whether the email fields are matching and submitting the form only if they are. Using `return` inside `beforeAction` will prevent the form submit event.

After submitting the form, we can run functionality depending on the result we received, via event listeners.

`action-success` event will fire if the form is submitted successfully. Inside this event, you can access the status code, data received and parameters you sent. In the example above, we are hiding the form and showing a success message.

`action-error` event will fire if the form is not submitted successfully. Inside this event, you can access the same data as `action-success`, with the addition of an error object. In the example above, we are controlling the error object and if it includes any non-field-errors, we are displaying them accordingly.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.akinon.com/technical-guides/project-zero/django/page-types/account-page/forms-and-validation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
