diff --git a/CHANGELOG.md b/CHANGELOG.md index a8f5b02..45a6b36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# v4.0.1 + +- [+] Добавлена ValueModel +- [*] FieldModel переименована в FormFieldModel и наследует ValueModel с возможностью добавления валидаторов + # v4.0.0 - [*] AppParamsStore: в конструктор добавлен аргумент `apiUrl` diff --git a/package.json b/package.json index 5331ac1..5941e49 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ktsstudio/mediaproject-stores", - "version": "4.0.0", + "version": "4.0.1", "author": "KTS Studio", "license": "MIT", "description": "Package with basic MobX stores for mediaprojects", diff --git a/src/models/FieldModel/FieldModel.ts b/src/models/FieldModel/FieldModel.ts deleted file mode 100644 index 9e34f2d..0000000 --- a/src/models/FieldModel/FieldModel.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { action, computed, makeObservable, observable } from 'mobx'; - -import { IField } from './types'; - -class FieldModel implements IField { - private _value: T; - private readonly _initialValue: T; - - constructor(value: T, config?: { initialValue: T }) { - this._value = value; - this._initialValue = - config?.initialValue === undefined ? value : config.initialValue; - - makeObservable, '_value'>(this, { - _value: observable.ref, - - value: computed, - - changeValue: action.bound, - reset: action.bound, - }); - } - - get value(): T { - return this._value; - } - - changeValue(value: I): I { - this._value = value; - - return value; - } - - reset(): void { - this._value = this._initialValue; - } -} - -export default FieldModel; diff --git a/src/models/FieldModel/index.ts b/src/models/FieldModel/index.ts deleted file mode 100644 index 67796d1..0000000 --- a/src/models/FieldModel/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default as FieldModel } from './FieldModel'; - -export * from './types'; diff --git a/src/models/FieldModel/types.ts b/src/models/FieldModel/types.ts deleted file mode 100644 index 5bb3f6f..0000000 --- a/src/models/FieldModel/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface IField { - get value(): T; - - changeValue(value: T): void; - reset(): void; -} diff --git a/src/models/FormFieldModel/FormFieldModel.ts b/src/models/FormFieldModel/FormFieldModel.ts new file mode 100644 index 0000000..043ce4f --- /dev/null +++ b/src/models/FormFieldModel/FormFieldModel.ts @@ -0,0 +1,72 @@ +import { action, computed, makeObservable, observable } from 'mobx'; + +import { ValueModel } from '../ValueModel'; + +import { FormFieldInitDataType, ValidatorType } from './types'; + +type ProtectedFields = '_error' | '_setError' | '_resetError'; + +export default class FormFieldModel extends ValueModel { + protected readonly _validators: ValidatorType[]; + + protected _error: string | null = null; + + constructor(initData: FormFieldInitDataType) { + super(initData.value); + + this._validators = initData.validators; + + makeObservable, ProtectedFields>(this, { + _error: observable, + + error: computed, + hasError: computed, + + _setError: action.bound, + _resetError: action.bound, + }); + } + + get error(): string | null { + return this._error; + } + + get hasError(): boolean { + return this._error !== null; + } + + setValue(value: T): void { + super.setValue(value); + + if (value === this.value) { + return; + } + + this._resetError(); + } + + protected _setError(value: string): void { + this._error = value; + } + + protected _resetError(): void { + this._error = null; + } + + validate(): void { + this._validators.some((validator) => { + const error = validator(this.value); + + if (error) { + this._setError(error); + } + + return Boolean(error); + }); + } + + reset(): void { + super.reset(); + this._resetError(); + } +} diff --git a/src/models/FormFieldModel/index.ts b/src/models/FormFieldModel/index.ts new file mode 100644 index 0000000..eddbb50 --- /dev/null +++ b/src/models/FormFieldModel/index.ts @@ -0,0 +1,3 @@ +export { default as FormFieldModel } from './FormFieldModel'; + +export * from './types'; diff --git a/src/models/FormFieldModel/types.ts b/src/models/FormFieldModel/types.ts new file mode 100644 index 0000000..15b1574 --- /dev/null +++ b/src/models/FormFieldModel/types.ts @@ -0,0 +1,6 @@ +export type ValidatorType = (value: T) => string | null; + +export type FormFieldInitDataType = { + value: T; + validators: ValidatorType[]; +}; diff --git a/src/models/ValueModel/ValueModel.ts b/src/models/ValueModel/ValueModel.ts new file mode 100644 index 0000000..294ca9c --- /dev/null +++ b/src/models/ValueModel/ValueModel.ts @@ -0,0 +1,57 @@ +import { action, computed, makeObservable, observable } from 'mobx'; + +type ProtectedFields = '_value' | '_touched' | '_resetTouched'; + +export default class ValueModel { + protected _value: T; + protected _touched = false; + protected readonly _initialValue: T; + + constructor(value: T) { + this._value = value; + this._initialValue = value; + + makeObservable, ProtectedFields>(this, { + _value: observable, + _touched: observable, + + value: computed, + isEmpty: computed, + touched: computed, + + setValue: action.bound, + reset: action.bound, + _resetTouched: action.bound, + }); + } + + get value(): T { + return this._value; + } + + get touched(): boolean { + return this._touched; + } + + get isEmpty(): boolean { + return !this._value; + } + + setValue(value: T): void { + if (value === this._value) { + return; + } + + this._value = value; + this._touched = true; + } + + protected _resetTouched = (): void => { + this._touched = false; + }; + + reset(): void { + this.setValue(this._initialValue); + this._resetTouched(); + } +} diff --git a/src/models/ValueModel/index.ts b/src/models/ValueModel/index.ts new file mode 100644 index 0000000..faf55f0 --- /dev/null +++ b/src/models/ValueModel/index.ts @@ -0,0 +1 @@ +export { default as ValueModel } from './ValueModel'; diff --git a/src/models/index.ts b/src/models/index.ts index 71d1201..1ed6cc5 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -10,4 +10,6 @@ export * from './BlurAndFocusHandlerModel'; export * from './PollingModel'; -export * from './FieldModel'; +export * from './FormFieldModel'; + +export * from './ValueModel';