Skip to content
Utilities form controls on base mobx for validation
TypeScript
Branch: master
Clone or download
Latest commit dca2925 Oct 9, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src Документация Oct 8, 2019
.gitignore Created project Oct 3, 2019
.prettierrc Created project Oct 3, 2019
LICENSE Initial commit Oct 3, 2019
README.md Update README.md Oct 9, 2019
package-lock.json add extensions for component Oct 3, 2019
package.json Меню в Документации Oct 8, 2019
tsconfig.json configuration Oct 3, 2019
tslint.json Created project Oct 3, 2019

README.md

mobx-form-validation-kit

Version License contributions welcome

Плюсы пакета

  • Полностью на TypeScript
  • Совместимость с Mobx (версии 4, который поддерживает, всеми любимый, IE10)
  • Рассчитан на работу в React (можно использовать в проектах и без react)
  • Рассчитан на асинхронные валидации
  • Легко встроить в существующий проект.

Установка

npm install @quantumart/mobx-form-validation-kit

FormControl

@quantumart/mobx-form-validation-kit позволяет создать прослойку между исходными данными и формой для отображения. Что, в свою очередь, позволяет валидировать их и, при необходимости, изменять данных перед тем как они попадут в исходный объект. Библиотека @quantumart/mobx-form-validation-kit содержит три основных класса (валидационных компонента) для управления формой:

Имя Описание
FormGroup позволяет объединять валидационные компоненты вместе. Класс типизированный, и позволяет переделать в качестве generic параметра интерфейс со списком полей. По умолчанию прописан any, крайне не рекомендуется использовать его без типизации, но возможность есть.
FormControl используется для валидации конкретного поля, наиболее часто используемый класс. Класс типизированный, и в качестве generic параметра принимает тип переменной которой должен хранить. По умолчанию прописан string, т.к. по умолчанию является строковым, как наиболее частный вариант для форм.
FormArray вызволят создавать и управлять массивом вариационных компонентов.

Кроме этого есть базовые абстрактные классы

Имя Описание
AbstractControl базовый класс для всех перечисленных валидационных классов, не типизирован.
FormAbstractControl базовый класс для FormGroup и FormArray, не типизирован.
FormAbstractGroup не типизированный базовый класс для FormControl, содержит ссылку на html элемент который отрисовывается.

Лучшей практикой по созданию валидирующей формы будет следующая идея. На форму создается объект типа один FormGroup и в нем уже перечисляются поля

this.form = new FormGroup<IUserInfo>({
      name: new FormControl(
            this.userInfo.name,
            [],
            v => (this.userInfo.name = v)
      ),
      surname: new FormControl(
            this.userInfo.surname,
            [],
            v => (this.userInfo.surname = v)
      )
      // …
    });

FormGroup поддерживает вложенность, т.е.

this.form = new FormGroup<IUserInfo>({
      name: new FormControl(
            this.userInfo.name,
            [],
            v => (this.userInfo.name = v)
      ),
      surname: new FormControl(
            this.userInfo.surname,
            [],
           v => (this.userInfo.surname = v)
      )
      passport: new FormGroup<IPassport >({
            number: new FormControl(
                  this.userInfo.passport.number,
                  [],
                  v => (this.userInfo.passport.number = v)
              ),
              // …
      })
      // …
    });

Можно добавить FormArray, который в свою очередь может быть передан тип FormControl и или целый FormGroup создавая объекты любой сложности и структуры.

  • FormArray<FormControl>
  • FormArray<FormGroup>

Сам по себе FormControl принимает следующий набор параметров в конструктор

Имя Описание
value типизированное изначальное значение.
validators набор валидаторов.
callbackValidValue callback функция в которое передается последние валидное значение. Она вызывается каждый раз, когда изменилось значение в FormControl и это значение проходит описанные валидации.
activate функция позволят включать/отключать валидаций по условию (по умолчанию включено всегда). Например, валидность даты окончания услуги не нужно проверять, если не стоит галочка «Безлимитный». Как следствие, просто вписав сюда функцию которая проверив состояния observable поля отвечающего за чекбокс «Безлимитный», можно автоматически отключить все валидации привязанные к полю на проверку даты, а не прописывать эту логику в каждую из валидаций поля дата.
additionalData блок с дополнительной информацией позволяет добавить дополнительную информацию к конкретному FormControl и использовать их в дальнейшем, например для визуализации. Это удобно, если есть билдеры для FormControl в которых нужно захаркодить определённую информацию, а не передавать это информацию через сложную связку данных в контролы для визуализации. Хотя точного и неоспоримого сценария применения я не смогу привести, но лучше иметь такую возможность, чем страдать без нее.

Есть одно ограничение, которое также присутствует и FormControl от Angular, не нужно переиспользовать объекты на разных формах. Т.е. можно создать билдер FormGroup и на каждую страницу создавать собственный объект. Но использовать один объект на кучу страниц - плохая практика. Более того FormControl инициализируется одним значением, и если это значение будет изменено, новое значение не попадет в FormControl. Сделано это специально, ибо, как показала практика, почему-то, все упорно пытаются изначально править исходный объект в обход валидаций, а не значение в FormControl. Просто присвоите новое значение полю value FormControl чтобы изменить исходный объект. FormGroup принимает следующий набор параметров в конструктор:

Имя Описание
controls объект унаследованный от AbstractControls. По факту просто создаете interface унаследованный от AbstractControls в котором перечисляете поля типа FormGroup, FormControl,
validators набор валидаторов для групповых значений. Например, можно создать FormGroup содержащий в себе два значения - минимальную и максимально дату, для контролла выбора периода. Именно в эти валидаторы нужно будет передать функцию/функции проверки диапазона дат. Например, что дата начала не больше дата конца
activate функция позволят включать/отключать валидаций по условию (по умолчанию включено всегда). Надо понимать, что применение функции валидации к группе отключает проверку на уровне всей группы. Например, у нас есть выпадашка выбора документа удостоверяющего личность. Можно создать несколько FormGroup с разным набором полей для документов: паспорт, водительское удостоверение, паспорт моряка и т.д.. В этой функции проверять значения выпадашки, и если выбранное значение не соответствует данной группе то отключаются все валидационные проверки. Точнее сказать – группа будет считаться валидной, в независимости от значений в ней.

Давайте поговорим о полях FormControl, в том числе они присутствую и FormGroup, и в FormArray.

Имя Описание
ControlTypes тип контрола (Control, Group, Array)
processing в процессе анализа. Т.к. поддерживаются асинхронные валидации, нарпимер те, что требуют запроса на сервер. Текущее состояние проверки можно узнать по данному полю.

Кроме этого FormGroup и FormArray поддерживают метод wait, который позволяет дождаться окончания проверки. Например при нажатии на кнопку «отправить данные» нужно прописать следующую конструкцию.

await this.form.wait();
	if (this.form.invalid) {
	…
Имя Описание
disabled проверка ошибок отключена (контрол всегда валиден)
active проверка ошибок включена. Зависит от результата выполнения функции активации. Данное значение очень удобно использовать для скрытия группы полей на форме и не писать дополнительные и дублирующие функции бизнес логики.
invalid для FormControl – означает, что поле содержит валидационные ошибки. Для FormGroup и FormArray означает, либо сам групповой контрол содержит ошибки, либо одно из вложенных полей (на любом из уровней вложенности) содержит ошибки валидации. Т.е. для проверки валидности всей формы достаточно выполнить одну проверку invalid или valid верхнего FormGroup.
valid для FormControl – означает, что поле не содержит валидационные ошибки. Для FormGroup и FormArray означает, либо сам групповой контрол не содержит ошибки, и ни одно из вложенных полей (на любом из уровней вложенности) не содержит ошибки валидации.
pristine значение в поле, после инициализации дефолтным значением, не изменялось.
dirty значение в поле, после инициализации дефолтным значением, менялось.
untouched для FormControl – означает, что поле (например input) не было в фокусе. Для FormGroup и FormArray означает, что ни один из вложенных FormControl-ов не был в фокусе. Значение false в этом поле означает, что фокус был не только был поставлен, но и снят с поля.
touched для FormControl – означает, что поле (например input) было в фокусе. Для FormGroup и FormArray означает, что один из вложенных FormControl-ов был в фокусе. Значение true в этом поле означает, что фокус был не только был поставлен, но и снят с поля.
focused для FormControl – означает, что поле (например input) сейчас в фокусе. Для FormGroup и FormArray означает, что один из вложенных FormControl-ов сейчас в фокусе.
errors поле содержит ошибки валидации. В отличии от перечисленных полей, данный массив содержит именно ошибки либо FormControl, либо FormGroup, либо FormArray, т.е. ошибки данного контрола, а не все вложенные. Влияет на поле valid / invalid
warnings поле содержит сообщения "Внимание". В отличии от перечисленных полей, данный массив содержит именно ошибки либо FormControl, либо FormGroup, либо FormArray, т.е. сообщения данного контрола, а не все вложенные. Не влияет на поле valid / invalid
informationMessages поле содержит сообщения "информационные сообщения". В отличии от перечисленных полей, данный массив содержит именно ошибки либо FormControl, либо FormGroup, либо FormArray, т.е. сообщения данного контрола, а не все вложенные. Не влияет на поле valid / invalid
successes поле содержит дополнительные сообщения о валидности. В отличии от перечисленных полей, данный массив содержит именно ошибки либо FormControl, либо FormGroup, либо FormArray, т.е. сообщения данного контрола, а не все вложенные. Не влияет на поле valid / invalid
maxEventLevel() максимальный уровень валидационных сообщении содержащих в поле в текущий момент. Метод вернет одно из значений enum, в следящем приоритете. - ValidationEventTypes.Error; - ValidationEventTypes.Warning; - ValidationEventTypes.Info; - ValidationEventTypes.Success;
serverErrors после отправки сообщения на сервер, хорошим тоном является проверка валидности формы и на сервере. Как следствие сервер может вернуть ошибки финальной проверки формы, и именно для таких этих ошибок предназначается массив serverErrors. Ключевой особенность serverErrors – является автоматическая очистка валидационных сообщений при потере фокуса с поля к которому были присвоены серверные ошибки, а также очистка серверных ошибок осуществляется если поле было изменено.
onChange кроме стандартного механизма mobx - reaction можно использовать delegate и добавить к нему callback функцию, которая вызовется при изменении данных.
setDirty(dirty: boolean) метод позволят изменить значение полей pristine / dirty
setTouched(touched: boolean) метод позволят изменить значение полей untouched / touched
dispose() обязателен к вызову в componentWillUnmount контрола отвечающего за страницу.

Это были общие поля для всех контролов, но каждый контрол также имеет и уникальные для свое типа поля. FormControl.

Имя Описание
value содержит текущее значение поля. Также данному полю можно присвоить новое значение.

FormGroup и FormArray содержат

Имя Описание
wait() метод позволяет ожидать окончания проверок всех (валидаций) в том числе и вложенных
allControls() данный метод позволяет получить полный набор всех FormControl в том числе и вложенных на разных уровнях. Т.е. по факту он разворачивает многоуровневый объект FormGroup, который также может содержать в себе FormGroup, в один большой список состоящий только из FormControl.

Функцонал allControls потребуется, если мы хотим найти первый невалидный элемент и поставить на него фокус. код, в таком случае будет выглядеть так:

await this.form.wait();
    if (this.form.invalid) {
      this.form.setTouched(true);
      const firstError = this.form.allControls().find(c => c.invalid && !!c.element);
      if (!!firstError) {
        firstError.element.focus();
      }
    }
...

Валидацииa

Конечно, кроме контролов, которые позволяют работать с данными, нам потребуется сами валидации. Пакет @quantumart/mobx-form-validation-kit естественно содержит ряд предустановленных валидаций, а также поддерживает создание собственный кастомных валидаций. Пример задания валидаций для FormControl для поля с указанием возраста.

new FormControl<number>(
        this.userInfo.age,
        [required(), minValue(18, "Вам должно быть больше 18 лет.", ValidationEventTypes.Warning)],
        v => (this.userInfo.age = v)
      )

Каждая валидация последними параметрами принимает:

Имя Описание
Message валидационное сообщение.
eventType уровень сообщения. Поддерживается 4 уровня сообщений.
  • Error - ошибки
  • Warning - предупреждения
  • Info – информационные сообщения
  • Success – сообщения о валидности. Например, можно проверить, что пароль действительно сложный.

В пакете идет следующий набор валидаций:

Имя Описание
required(… обязательное поле
notEmptyOrSpaces(… поле не пустое и не содержит одни пробелы. По факту required с учетом запрета пробелов.
pattern(regExp: RegExp, … первым параметром идет регулярное выражение, которому должно соответствовать поле. Ошибка выдается, если нет соответствия паттерну.
invertPattern(regExp: RegExp, … первым параметром идет регулярное выражение, которому не должно соответствовать поле. Ошибка выдается, если есть соответствия паттерну.
minLength(minlength: number, …. первым параметром идет минимальная длина текста включительно. Ошибка выдается если длина меньше переданной.
maxLength(maxlength: number, …. первым параметром идет максимальная длина текста включительно. Ошибка выдается если длина больше переданной.
absoluteLength(length: number, …. первым параметром идет точная длина текста. Ошибка выдается если длина не соответствует заданной.
minValue(min: TEntity (() => TEntity) , …. данная валидация предназначена только для чисел и дат. Ошибка устанавливается, если значение меньше указанного. Особенность валидации является возможность принимать в качестве первого параметра не только конкретное значение, но и функцию. Что означает, что если считывать значение в этой функции с @observable поля объекта, валидация сама будет перезапускаться не только при изменении поля на которое повешена валидация, но и также и при изменении «связанно поля». При этом не требуется никаких дополнительных манипуляций кроме как пометить поле с которого считывается значение как @observable.
maxValue(max: TEntity (() => TEntity) , …. данная валидация предназначена только для чисел и дат. Ошибка устанавливается, если значение больше указанного. Особенность валидации является возможность принимать в качестве первого параметра не только конкретное значение, но и функцию. Что означает, что если считывать значение в этой функции с @observable поля объекта, валидация сама будет перезапускаться не только при изменении поля на которое повешена валидация, но и также и при изменении «связанно поля». При этом не требуется никаких дополнительных манипуляций кроме как пометить поле с которого считывается значение как @observable
notContainSpaces(… в отличии от notEmptyOrSpaces, ошибка будет выдаваться если в значении вообще будет хоть один пробел.
compare(expression: (value: TEntity) => boolean(… написание собственной функции-валидации порождает много копипастного кода, для избавления этой проблемы была разработана эта обертка. Эта валидационная функция первым параметром принимает функцию, в которую в свою очередь передается текущее значение поля. Что позволяет сделать сложную проверку. Например, расчет хеша для ИНН или номера паспорта. И после вернуть true/false. Ошибка будет отображена, если проверка вернула false.
isEqual(value: string… простая проверка на соответствие строке.

Далее описаны функции обертки, которые служат для управления потоком запуска валидаций. Нужно отметить, что переданный в FormControl, FormGroup, FormArray набор валидаций запускается единым скопом и по факту не имеет последовательности выполнения. Итогом работы мы будем иметь в полях errors, warnings, informationMessages, successes массивы состоявшие из объеденных в единый массив ошибок, предупреждений и т.д..
Часто заказчик хочет увидеть лишь одну ошибку, а не все сразу. Более того, ТЗ может быть составлено так, что одна проверка выполняется только после того как прошла предыдущая. Для решения данной проблемы применяется обертка wrapperSequentialCheck. Ей вызов и её применение не чем не отличается от обычной функции-валидатора, но на вход она принимает массив из валидаторов которые будет запускается последовательно, т.е. следующая валидация запуститься только после того, что предыдущая прошла без ошибок. Второй функций оберткой является функция управления потоком валидаций. wrapperActivateValidation первым параметром принимает функцию в которой нужно прописать условия активаций валидаций. В отличии от функции activate которая передается в FormControl данная проверка рассчитана на более сложную логику. Предположим, что у нас общий билдер для целой формы FormGroup платежей, и более того на сервере есть только один метод который и принимает общий набор полей. Но вот загвоздка в том, что хоть форма и одна, в зависимости от «типа платежа» мы показываем различный набор полей пользователю. Так вот wrapperActivateValidation позволяет написать логику при которой будет осуществляться различные проверки в зависимости от типа платежа. Выглядеть применение оберток будет точно также, как и обычных функций.

new FormControl(
        this.userInfo.megapole,
        [wrapperActivateValidation(() => this.info.A === 10, [
                required(),
                pattern(/\^d{10}$/)
        ]),
        wrapperActivateValidation(() => this.info.A === 20, [
                wrapperSequentialCheck([
                        notContainSpaces(),
                        pattern(/\^d{20}$/)
                ])
        ])],
        v => (this.userInfo.megapole = v)
      )

Из данного примера видно, что проверки required(), pattern(/^d{10}$/) будут осуществляться только при this.info.A === 10, а в случае если this.info.A === 20, то сработают валидации notContainSpaces(), pattern(/^d{20}$/), кроме того эти валидации сработают последовательно, в отличии от первого случая.

Естественно, наступит момент когда стандартного набора валидаций уже не будет хватать. Тогда придется писать собственные асинхронные функции. Благо это делается без особых сложностей. FormControl изначально затачивался на асихронные валидационые функции, которым может захотеться сходить на сервер на данными и этот ответ нужно ждать. А как следствие все валидации являются асинхронными.

async function checkValueOnServer(control: FormControl): Promise<ValidationEvent[]> {
    if (control.value == null) {
      return [];
    }
    const result = await sendToServer(control.value);
    if (result.errorMessage) {
      return [
        {
          message: result.errorMessage,
          type: ValidationEventTypes.Error,
        },
      ];
    }
    return [];
}

Тут нужно обратить внимание на два объекта. Первый мы всегда возражающем массив. Т.е. по факту можно вернуть сразу несколько ошибочных сообщений, если вам будет угодно. Второй момент это возвращаемый объект, он имеет следующий набор полей.

Имя Описание
key необязательное поле, позволяет задать "ключ" для конкретной валидаций. У всех базовых key уникален и совпадает с их именем. Может возникнуть желание, использовать key для рендернга списка в react, но как показала практика это плохая идея. В дальнейшем, в примере, я покажу, что лучше использовать message, а key вообще не трогать. В любом случае он есть, как и в Angunar, но вот его необходимость сведена, по факту, к 0.
message валидационное сообщение. Обязательное поле.
type тип сообщения. - Error - ошибки - Warning - предупреждения - Info – информационные сообщения - Success – сообщения о валидности. Например, можно проверить, что пароль действительно сложный.
additionalData дополнительная информация которую можно передать вместе с валидацией, если это необходимо. Это может быть какая-то дополнительная html разметка или специфичный стиль. В общем-то в any можно засунуть всё.

Extensions

Любая магия основывается на тривиальных вещах. И в этом случае, для работы постановки фокуса, получение изменений с полей требуется связать FormControl в конкретным полем ввода. Т.к. FormControl не ограничивает разработчика в типе валидируемых данных, то из-за универсальности пришлось немного пожертвовать применимостью в react элементам. При этом, для input и textarea удалось создать простые функции биндинга данных на элемент, для остальных компонентов, обработчику придется все же приложить минимальные усилия для подстановки данных.

Для input биндинг элемента на FormControl (name) будет выглядеть так. <input type="text" {...InputFormControl.bindActions(controls.name)} /> Для textarea биндинг будет таким <textarea {...TextAreaFormControl.bindActions(controls.name)}/>

InputFormControl.bindActions и TextAreaFormControl.bindActions принимаю два параметра:

Имя Описание
formControl собственно FormControl на который будет приходиться биндинг. Обязательный параметр.
events Необязательный параметр, содержащий список функций, которые можно вызвать в случае необходимости их кастомизации. Суть в том, что bindActions навешивает функции-обработчики событий на Element, а как следствие, перекрытие этих событий в element приведет к неработоспособности либо FormControl-а, либо функции разработчика. Для решения этой проблемы. Мы передаем нужную кастомную функцию разработка в объект event. Сейас поддерживается следующий набор методов. - ref - onChange - onBlur - onFocus

При использовании библиотеки вы сможете заменить, что наиболее частым вариантом создания FormControl-ов является следующая конструкция.

this.form = new FormGroup<IUserInfo>({
      name: new FormControl(
        this.userInfo.name,
        [],
        v => (this.userInfo.name = v)
      )
    });

Наибольшей проблемой здесь является двойное упоминание this.userInfo.name, для изначально инициализации FormControl и для записи результата. Такая связка может породить нежелательные проблемы во время копипаста и для их решения была разработана функция FormControl.for

this.form = new FormGroup<IUserInfo>({
      name: FormControl.for(this.userInfo, 'name', [])
    });

Как можно видеть, теперь не требуется повторять обращение к полю name name два раза. Причем, благодаря возможностям типизации в TypeScript, строка name, действительно отслеживается как поле. И если такого поля не будет в объекте userInfo - мы получим ошибку компиляции.

Если вы дочитали досюда - вы уже герой. :)

Пример

Демонстрацию будем проводить на React проекте на TypeScript с использованием mobx. Для существующего проекта мы просто добавляем пакет.

npm install @quantumart/mobx-form-validation-kit

Компонент Hello в страницу регистрации. Для этого создадим класс RegistrationStore в новом файле RegistrationStore.ts src\RegistrationStore.ts

import { observable } from "mobx";

export class RegistrationStore {
  @observable
  public userInfo = {
    name: "Виталий"
  };
}

export const registrationStore = new RegistrationStore();

Файл Hello.ts, модифицируем так.

import * as React from "react";
import { observer } from "mobx-react";
import { registrationStore } from "../RegistrationStore";

@observer
export class Hello extends React.Component {
  private changeName = (event: React.ChangeEvent<HTMLInputElement>) => {
    registrationStore.userInfo.name = event.target.value;
  };
  render() {
    return (
      <React.Fragment>
        <h1>Здравствуйте, {registrationStore.userInfo.name}</h1>
        <div className="row">
          <span>Имя:</span>
          <input
            type="text"
            value={registrationStore.userInfo.name}
            onChange={this.changeName}
          />
        </div>
      </React.Fragment>
    );
  }
}

В итоге получился уже функциональный компонент, со Store работающим через Mobx. Можно уже увидеть результат работы в виде динамически меняющихся текстов на странице при вводе информации в input. Но во всей этой красоте, есть проблема. Чем больше полей у нас добавляется, тем больше методов изменений нам придется написать. А после добавления кнопки «отправить» нужно будет не забыть проверить все поля с учетом их с видимости. И с каждым новым полем количество копипаста будет только увеличиваться, не говоря уже про сложное переиспользование кода. Для решения этой кучи проблем была создана @quantumart/mobx-form-validation-kit

Для начала создадим небольшой компонент-обертку для визуализации ошибок. stc/ErrorWraper.tsx

import * as React from "react";
import { observer } from "mobx-react";
import { FormControl } from "@quantumart/mobx-form-validation-kit";

interface Props {
  formControl: FormControl;
}

@observer
export class ErrorWraper extends React.Component<Props> {
  render() {
    return (
      <div>
        {this.props.children}
        {this.props.formControl.errors.map(error => (
          <span key={error.message} className="error">
            {error.message}
          </span>
        ))}
      </div>
    );
  }
}

В нем нет ничего сложного, просто выводим красный текст сообщений-ошибок, если они есть.

Компонент Hello.tsx модифицируется тоже не сильно. Во-первых - убирается лишний метод changeName. Вместо него добавилась строка биндинга {...InputFormControl.bindActions(controls.name)}. В ней содержится все необходимые методы которые позволят реагировать на изменения данных. Во-вторых – мы добавили обертку для input, конечно лучше сделать отдельный компонент с input внутри, но тогда, для пояснений, потребуется немного более сложна структура. В-третьих – в конструктор добавлена функция которая инициализирует form в store, а, самое главное, в componentWillUnmount прописали registrationStore.form.dispose(). Без это вызова могут mobx реакции которые развешивает FromControl могут так и остаться жить до самой перезагрузки страницы.

import * as React from "react";
import { observer } from "mobx-react";
import { registrationStore } from "../RegistrationStore";
import { ErrorWraper } from "../ErrorWraper";
import { InputFormControl } from "@quantumart/mobx-form-validation-kit";

@observer
export class Hello extends React.Component {
  constructor(props: any) {
    super(props);
    registrationStore.initForm();
  }
  componentWillUnmount() {
    registrationStore.form.dispose();
  }
  render() {
    const controls = registrationStore.form.controls;
    return (
      <React.Fragment>
        <h1>Здравствуйте, {registrationStore.userInfo.name}</h1>
        <div className="row">
          <span>Имя:</span>
          <ErrorWraper formControl={controls.name}>
            <input
              type="text"
              {...InputFormControl.bindActions(controls.name)}
            />
          </ErrorWraper>
        </div>
      </React.Fragment>
    );
  }
}

Дополнительным изменения подвергся и файл RegistrationStore.ts. Он приобрёл следующую структуру. Основным объектом (исходным объектом) с информацией о пользователе остался userInfo, но кроме этого появилась прослойка в виде form. Именно эта прослойка будет отвечать за валидации и за-за присвоения данных объекту userInfo.

import { observable } from "mobx";
import {
  FormControl,
  FormGroup,
  AbstractControls
} from "@quantumart/mobx-form-validation-kit";

interface IUserInfo extends AbstractControls {
  name: FormControl;
}

export class RegistrationStore {
  @observable
  public userInfo = {
    name: "Виталий"
  };

  @observable
  public form: FormGroup<IUserInfo>;

 public initForm(): void {
    this.form = new FormGroup<IUserInfo>({
      name: new FormControl(
        this.userInfo.name,
        [],
        v => (this.userInfo.name = v)
      )
    });
  }
}
export const registrationStore = new RegistrationStore();

Об авторе

Пакет разработан в компании Quantum Art одним из лидеров рынка разработки технологически сложных интернет/интранет решений.

  • Виталий Алферов - ведущий разработчик пакета.
You can’t perform that action at this time.