apphouse
Version:
Component library for React that uses observable state management and theme-able components.
152 lines (142 loc) • 3.43 kB
text/typescript
import { makeAutoObservable, runInAction, toJS } from 'mobx';
import { InputProps } from '../../components/input/input.interface';
import { validateField } from './utils/validateField';
import { FieldType, FormFieldOptions, FormFieldType } from './Field.interface';
import { getValidationFun } from './utils/getValidationFunction';
/**
* A model to represent a field in a form.
*/
export class Field {
/**
* The id of the field. It must be unique for the form.
*/
id: string;
/**
* The value of the field.
*/
value: string | undefined;
/**
* The type of the field.
* @default 'text'
*/
type: FormFieldType;
/**
* Options for the field if the field is of type `option`.
*/
options?: FormFieldOptions;
/**
* The prop options for the input component.
*/
input?: Partial<InputProps>;
/**
* A function to validate the value of the field.
* @optional Defaults will be used if not provided.
*/
validation?: (value?: string) => boolean;
constructor(props: FieldType) {
this.id = props.id;
this.value = props.value;
this.type = props.type || 'text';
this.options = props.options;
this.input = props.input;
this.validation = props.validation;
makeAutoObservable(this);
}
/**
* Whether the field is valid or not.
*/
get valid() {
const required: boolean = this.input?.required || false;
const validationFun = getValidationFun(this.type, this.validation);
return validateField(this.value, required, validationFun);
}
/**
* Sets the value of the field.
* @param value the value to set the field to
*/
set = (value?: string) => {
runInAction(() => {
this.value = value;
});
};
/**
* Sets the input to be disabled
* @param disabled
*/
setDisabled = (disabled: boolean) => {
runInAction(() => {
if (this.input) {
this.input.disabled = disabled;
} else {
this.input = { disabled };
}
});
};
/**
* Sets the input to be required
* @param required
*/
setRequired = (required: boolean) => {
runInAction(() => {
if (this.input) {
this.input.required = required;
} else {
this.input = { required };
}
});
};
/**
* Sets the min value of input
* *Only applies to number, date, input types*
* @param min
*/
setMin = (min: string) => {
if (this.type !== 'number' && this.type !== 'date') {
throw new Error(
'setMin can only be used with number and date input types'
);
}
runInAction(() => {
if (this.input) {
this.input.min = min;
} else {
this.input = { min };
}
});
};
/**
* Sets the max value of input
* *Only applies to number, date, input types*
* @param min
*/
setMax = (max: string) => {
runInAction(() => {
if (this.input) {
this.input.max = max;
} else {
this.input = { max };
}
});
};
/**
* Clears the value of the field.
*/
clear = () => {
this.set(undefined);
};
/**
* Get the field as a plain object.
* @returns the field as a plain object
*/
obj = (): FieldType => {
const field = toJS(this);
return {
id: field.id,
value: field.value || '',
type: field.type,
options: field.options,
input: field.input,
validation: field.validation
};
};
}