Form

Базовый компонент формы. Basic form component.

Import Permalink to "Import"

js
import ProximaForm from 'proxima-vue/form';
import ProximaFormFieldset from 'proxima-vue/form/fieldset';
import ProximaFormField from 'proxima-vue/form/field';

Example Permalink to "Example"


formValues: { "email": "", "password": "" }
formErrors: {}
html
<ProximaForm @submit="onFormSubmit">
  <ProximaFormField :is="ProximaEmail"
    name="email"
    label="Email"
    label-position="inside"
    v-model="formValues"
    v-model:errors="formErrors"
  />
  <ProximaFormField :is="ProximaPassword"
    name="password"
    label="Password"
    label-position="inside"
    v-model="formValues"
    v-model:errors="formErrors"
  />
  <template #footer>
    <ProximaButton type="submit" width="max" text="Sign In" />
  </template>
</ProximaForm>
js
import { ref } from 'vue';
import ProximaForm from 'proxima-vue/form';
import ProximaFormField from 'proxima-vue/form/field';
import ProximaPassword from 'proxima-vue/field/password';
import ProximaEmail from 'proxima-vue/field/email';
import ProximaButton from 'proxima-vue/button';

const formErrors = ref({});
const formValues = ref({
  email: '',
  password: '',
});

const onFormSubmit = () => {
  // The form is valid, you can post the values to the server.
};

Form Permalink to "Form"

Компонент ProximaForm проверяет валидность полей при отправке, если все хорошо, то будет вызвано событие submit, если же есть невалидное поле, то оно получит фокус, но это можно отключить: The ProximaForm component checks the validity of the fields upon submission. If everything is good, the submit event will be called. If there is an invalid field, it will receive focus, but this behavior can be disabled:

html
<ProximaForm
  :should-focus-on-submit-failed="false"
  @submit="onFormSubmit"
>
  ... fields
</ProximaForm>

Fieldset Permalink to "Fieldset"

Для группировки полей можно использовать ProximaFormFieldset: To group fields, you can use ProximaFormFieldset:

html
<ProximaForm @submit="onFormSubmit">
  <ProximaFormFieldset legend="First group">
    ... fields
  </ProximaFormFieldset>
  <ProximaFormFieldset legend="Second group">
    ... fields
  </ProximaFormFieldset>
</ProximaForm>

Также можно группировать поля на одной строке, для этого можно использовать пропс part: You can also group fields on one line; for this, you can use the part prop:

html
<!-- Two fields on one line -->
<ProximaFormField part="half" />
<ProximaFormField part="half" />

<!-- Three fields on one line -->
<ProximaFormField part="third" />
<ProximaFormField part="third" />
<ProximaFormField part="third" />

<!-- Four fields on one line -->
<ProximaFormField part="quarter" />
<ProximaFormField part="quarter" />
<ProximaFormField part="quarter" />
<ProximaFormField part="quarter" />

Field Permalink to "Field"

Компонент ProximaFormField ключевой элемент формы, у каждого поля должен быть name для управления состоянием, через пропс is можно указать какой компонент нужно использовать, по умолчанию это текстовое поле — The ProximaFormField component is an important element of the form. Each field must have a name to control the state. Through the is prop, you can specify which component should be used; by default, this is the text field — ProximaField

html
<!-- Text field, not required -->
<ProximaFormField
  name="username"
  label="Username"
  :required="false"
  v-model="formValues"
/>

<!-- Email field -->
<ProximaFormField :is="ProximaEmail"
  name="email"
  label="E-mail"
  v-model="formValues"
/>

Пропсы, которые не относятся к полю формы будут переданы своему дочернему компоненту, например label. Props that do not belong to the form field will be passed to its child component, such as the label.

Validation Permalink to "Validation"

По умолчанию валидация поля проверяется через метод checkValidity, эта функция уже встроена в переключатели, чекбоксы и поля данной библиотеки, для текстовых полей вы можете передать свою функцию валидации через пропс validator: By default, field validation is checked through the checkValidity method, which is already built into toggle buttons, checkboxes, and fields in this library. For text fields, you can pass your validation function through the validator prop:

html
<ProximaFormField :is="ProximaPassword"
  name="password"
  :validator="checkPassword"
  v-model="formValues"
/>
js
const checkPassword = (password) => {
  // Password must include digits and letters
  if (/d/.test(password) && /[a-z]/i.test(password)) {
    return true;
  }
  return false;
};

Поле формы позволяет использовать любой компонент, который поддерживает v-model, а для валидации такого поля можно передать свою функцию в пропс customValidator: The form field allows you to use any component that supports v-model, and you can validate such a field by passing your function to the customValidator prop:

html
<ProximaFormField :is="myCustomComponent"
  name="fieldName"
  :custom-validator="validateCustomComponent"
  v-model="formValues"
/>
js
const validateCustomComponent = (value) => {
  // validate value
  return true;
};

Errors Permalink to "Errors"

Поле формы поддерживает два вида ошибок plain и popup, для описания используются типовые ошибки, но вы можете передать свою функцию в пропс errorCreator и детально описать невалидное значение, данная функция может возвращать обычный текст или же глобальный токен локализации: The form field supports two types of errors: plain and popup. Standard errors are used for description, but you can pass your function to the errorCreator prop to describe the invalid value in detail. This function can return plain text or a global localization token:

html
<ProximaFormField :is="ProximaPassword"
  name="password"
  error-view="plain"
  :error-creator="createPasswordError"
  v-model="formValues"
  v-model:errors="formErrors"
/>
js
const createPasswordError = (value) => {
  if (!value) {
    return 'Please create a password';
    // or you can use the global locale token, for example:
    // return 'formErrorPasswordRequired';
  }
  if (value.length < 6) {
    return 'Password must be at least 6 characters';
  }
  return '';
};

Accessibility Permalink to "Accessibility"

Чтобы добавить описание поля для вспомогательных технологий нужно использовать пропс describedby, который добавляет полю атрибут aria‑describedby: To add a field description for assistive technologies, use the describedby prop, which adds the aria‑describedby attribute to the field:

html
<ProximaFormField
  describedby="my-hidden-description"
/>

<p id="my-hidden-description" hidden>
  The extended description for assistive technologies can be hidden
</p>

BEM Permalink to "BEM"

Блок компонента form, модификаторы (создаются автоматически на основе пропсов): Component block form, modifiers (automatically created based on props):

CSS Permalink to "CSS"

Слой компонента @layer proxima.form, также вы можете гибко cтилизовать компонент через кастомные свойства: Component layer @layer proxima.form, also you can style the component flexibly through custom properties:

css
--form-gap: 0.625rem;

/* Header */
--form-header-margin-y-end: 1rem;

/* Content */
--form-content-display: flex;
--form-content-flex-wrap: wrap;
--form-content-justify-content: stretch;

/* Footer */
--form-footer-gap: 0.5rem;
--form-footer-margin-y-start: 2rem;

/* Fieldset */
--form-fieldset-flex: 0 0 100%;
--form-fieldset-max-width: 100%;
--form-fieldset-margin-y-start: 2rem;

/* Legend */
--form-legend-font-family: inherit;
--form-legend-font-size: 1rem;
--form-legend-font-weight: 700;
--form-legend-line-height: 1.25;
--form-legend-letter-spacing: normal;
--form-legend-text-transform: none;
--form-legend-text-align: inherit;
--form-legend-color: inherit;
--form-legend-margin-y-start: 0;
--form-legend-margin-y-end: 0.75rem;

/* Field */
--form-field-flex: 0 0 100%;
--form-field-max-width: 100%;

/* Error */
--form-message-min-height: auto;
--form-error-font-size: 0.875rem;
--form-error-line-height: 1.25;
--form-error-padding-y-start: 0.25rem;
--form-error-color: var(--app-invalid-color);

/* Popup */
--form-popup-padding: 1rem 1.5rem;
--form-popup-border-inline-width: 0.25rem;
--form-popup-border-inline-color: var(--form-error-color);
--form-popup-box-shadow: 0 0.25rem 1rem rgba(0, 0, 0, 0.15);
Locale Permalink to "Locale"

Компонент использует токены локализации: The component uses localization tokens:


js
{
  fieldInvalid: "The field is not valid",
  fieldRequired: "The field is required",
}
Props Permalink to "Props"
ts
interface ProximaFormProps {
  shouldFocusOnSubmitFailed?: boolean
  shouldCheckValidity?: boolean
  footerAlign?: 'start' | 'center' | 'end'
}

interface ProximaFormFieldsetProps {
  legend?: string
}

interface ProximaFormFieldProps<Values> {
  id?: string
  is?: ProximaDynamicComponent
  name: keyof Values
  modelValue: Values
  errors?: Partial<Record<keyof Values, string>>
  errorView?: 'popup' | 'plain'
  errorCreator?: (value: any) => string
  customValidator?: (value: any) => boolean
  popupProps?: ProximaDynamicProps
  describedby?: string
  required?: boolean
  disabled?: boolean
  part?: 'half' | 'third' | 'quarter'
}
Events Permalink to "Events"
html
<ProximaForm
  @submit="onFormSubmit"
/>

<ProximaFormField
  @update:modelValue="onFormValuesUpdate"
  @update:errors="onFormErrorsUpdate"
  @update="onFieldUpdate"
  @focus="onFieldFocus"
  @blur="onFieldBlur"
/>
js
const onFormSubmit = () => {};

const onFormValuesUpdate = (values) => {};
const onFormErrorsUpdate = (errors) => {};
const onFieldUpdate = (event) => {};
const onFieldFocus = (event) => {};
const onFieldBlur = (event) => {};
ts
interface ProximaFormEvent<Values> {
  name: keyof Values
  value: any
  errorMessage: string
  validity: boolean
  field: ProximaFormFieldExposed
}

type ProximaFormEmits = {
  'submit': () => void
}

type ProximaFormFieldEmits = {
  'update:modelValue': (modelValue: Values) => void
  'update:errors': (errors: Partial<Record<keyof Values, string>>) => void
  'update': (event: ProximaFormEvent) => void
  'focus': (event: ProximaFormEvent) => void
  'blur': (event: ProximaFormEvent) => void
}
Slots Permalink to "Slots"
html
<ProximaForm>
  <template #header>
    you code (append to header)
  </template>

  <template #footer>
    you code (append to footer)
  </template>
</ProximaForm>

<!-- Fieldset -->
<ProximaFormFieldset>
  <template #legend>
    you code (replaced legend text)
  </template>
</ProximaFormFieldset>

<!-- Field -->
<ProximaFormField>
  <template #form-field-error="{ error, id }">
    you code (replaced plain error)
  </template>

  <template #form-field-error-popup="{ error, id }">
    you code (replaced popup error)
  </template>

  <!-- Other slots will be added to the child component -->
</ProximaFormField>
Expose Permalink to "Expose"
html
<ProximaForm ref="form">
  <ProximaFormField
    name="myfield"
  />
</ProximaForm>
ts
import { ref, unref, onMounted } from 'vue';
import ProximaForm from 'proxima-vue/form';
import ProximaFormField from 'proxima-vue/form/field';

const form = ref({} as InstanceType<typeof ProximaForm>);

onMounted(() => {
  const myfield = unref(form).getField('myfield');
  myfield.checkFocus(); // false
  myfield.focus();
  myfield.checkFocus(); // true
});
ts
type ProximaFormInstance = {
  getField: (name: string) => ProximaFormFieldInstance | undefined
  focusField: (name: string) => void
  checkFieldValidity: (name: string) => boolean
  checkValidity: () => boolean
  focus: () => void
  blur: () => void
}

type ProximaFormFieldInstance = {
  getErrorMessage: () => string
  getContainer: () => HTMLDivElement | null
  getElement: () => ComponentPublicInstance | null
  getValue: () => any
  getName: () => string
  checkFocus: () => boolean
  checkDisabled: () => boolean
  checkRequired: () => boolean
  checkValidity: () => boolean
  emitError: () => void
  focus: () => void
  blur: () => void
}
View source on GitHub