add InputRestriction support for reactiveValue.ts

This commit is contained in:
Maksim Skobaro 2025-02-08 03:33:42 +03:00
parent b1ea3a670e
commit a5695ccab6

View File

@ -1,11 +1,14 @@
import {action, computed, makeObservable, observable, reaction} from "mobx";
import _ from "lodash";
export class ReactiveValue<T> {
@observable private val: T;
@observable private isTouched: boolean = false;
@observable private validators: ((value: T, field: string) => string)[] = [];
@observable private inputRestrictions: ((value: T, field: string) => string)[] = [];
@observable private errors: string[] = [];
@observable private inputRestrictionError: string;
@observable private fieldName: string;
constructor(fireImmediately: boolean = false) {
@ -13,8 +16,10 @@ export class ReactiveValue<T> {
reaction(() => ({value: this.val, touched: this.isTouched}), () => {
if (!this.isTouched) {
this.errors = [];
this.inputRestrictionError = undefined;
return;
}
this.errors = this.validators
.map(validator => validator(this.val, this.fieldName))
.filter(error => error && error.length > 0);
@ -28,8 +33,23 @@ export class ReactiveValue<T> {
@action.bound
set(value: T) {
this.val = value;
this.isTouched = true;
this.inputRestrictionError = undefined;
if (!_.isEmpty(value)) {
for (const restriction of this.inputRestrictions) {
const error = restriction(value, this.fieldName);
if (error) {
this.inputRestrictionError = error;
}
}
}
const lengthIsLessIfStringOrTrue = _.isString(value) && _.isString(this.val) ? value.length < this.val?.length : true;
if (!this.inputRestrictionError || lengthIsLessIfStringOrTrue) {
this.setAuto(value);
}
return this;
}
@ -56,23 +76,35 @@ export class ReactiveValue<T> {
@action.bound
addValidator(validator: (value: T, field?: string) => string) {
this.validators.push(validator);
if (validator) {
this.validators.push(validator);
}
return this;
}
@action.bound
addInputRestriction(restriction: (value: T) => string) {
if (restriction) {
this.inputRestrictions.push(restriction);
}
return this;
}
@computed
get invalid() {
return this.errors.length > 0;
return this.errors.length > 0 || !!this.inputRestrictionError;
}
@computed
get allErrors() {
return this.errors;
return [...this.errors, this.inputRestrictionError].filter(error => error);
}
@computed
get firstError() {
return this.errors[0];
return this.inputRestrictionError ?? this.errors[0];
}
@action.bound
@ -87,9 +119,10 @@ export class ReactiveValue<T> {
@action.bound
clear() {
this.val = null;
this.val = undefined;
this.isTouched = false;
this.errors = [];
this.inputRestrictionError = undefined;
}
}