vault/ui/app/forms
Vault Automation 42780fbcf2
[UI] Ember Data Migration - OIDC Clients (#14288) (#14353)
* updates oidc clients list view to use api service

* updates oidc client and client details routes to use api service

* updates form field groups component to yield out form field yields

* adds oidc client form class

* updates oidc client client and edit routes to use api service

* updates oidc client-form component to use form class and removes store/model support

* updates oidc provider client route to use api service

* updates oidc key clients route to use api service

* fixes tests

Co-authored-by: Jordan Reimer <zofskeez@gmail.com>
2026-04-28 17:22:28 +00:00
..
auth license: update headers to IBM Corp. (#10229) (#10233) 2025-10-21 15:20:20 -06:00
oidc [UI] Ember Data Migration - OIDC Clients (#14288) (#14353) 2026-04-28 17:22:28 +00:00
secrets [UI][Bugfix] VAULT-43725 Add validations for LDAP roles create / edit forms (#13757) (#13859) 2026-04-10 07:43:56 -07:00
sync [UI] VAULT-42756 - Secret sync WIF implementation (#14001) (#14167) 2026-04-22 12:46:13 +05:30
v2 Add V2 Form generator script (#12062) (#12089) 2026-02-25 19:09:42 +00:00
custom-message.ts license: update headers to IBM Corp. (#10229) (#10233) 2025-10-21 15:20:20 -06:00
form.ts [UI] Ember Data Migration - PKI Configuration (#10328) (#10523) 2025-11-18 09:42:22 -07:00
mount.ts UI: fix bug when mounting external kv version & empty payload when tuning external versions (#13361) (#13450) 2026-03-26 16:58:42 -04:00
open-api.ts Update eslint console rule (#11883) (#11948) 2026-01-23 13:26:41 -08:00
README.md [UI] API Service Error Parsing (#30454) 2025-04-30 11:44:19 -06:00

Background

The Form class was created as a replacement for form related functionality that previously lived in Ember Data models. Given that the FormField component was designed around the metadata that was defined on model attributes, it was imperative to preserve this pattern while moving the functionality to a dependency-free native javascript solution.

Usage

The Form class is intended to be extended by a class that represents a particular form in the application.

export default class MyForm extends Form {
  declare data: MyFormData;

  // define form fields
  name = new FormField('name', 'string');
  secret = new FormField('secret', 'string', {
    editType: 'kv',
    keyPlaceholder: 'Secret key',
    valuePlaceholder: 'Secret value',
    label: 'Secret (kv pairs)',
    isSingleRow: true,
    allowWhiteSpace: true,
  });

  // define validations
  validations: Validations = {
    name: [{ type: 'presence', message: 'Name is required.' }],
  };

  // if serialization is needed override toJSON method
  toJSON() {
    const trimmedName = this.data.name.trim();
    return super.toJSON({ ...this.data, name: trimmedName });
  }
}

Form data is set to the data object on the class and can be initialized with defaults or server data when editing by passing an object into the constructor.

// create route
model() {
  return new MyForm({ name: 'Default name' });
}

// edit route
async model() {
  const data = await this.api.fetchSomeData();
  return new MyForm(data);
}

The route model (MyForm instance) can be passed into the form component in the same manner as an Ember Data model and the formFields can be looped to render FormField components.

{{#each @form.formFields as |field|}}
  <FormField @attr={{field}} @model={{@form}} @modelValidations={{this.validations}} />
{{/each}}

To validate the form and access the data use the toJSON method.

// save method of form component
async save() {
  try {
    const { isValid, state, invalidFormMessage, data } = this.args.form.toJSON();
    this.validations = isValid ? null : state;
    this.invalidFormMessage = invalidFormMessage;

    if (isValid) {
      await this.api.saveTheForm(data);
      this.flashMessages.success('It worked');
      this.router.transitionTo('another.route');
    }
  } catch(error) {
    const { message } = await this.api.parseError(error);
    this.errorMessage = message;
  }
}