Skip to main content

Forms & Validation

Forms in Account Pages

<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.

Validations

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.

PzForm Actions

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.