UNPKG

apollo-form

Version:
270 lines (269 loc) 9.32 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const cloneDeep_1 = __importDefault(require("lodash/cloneDeep")); const isEqual_1 = __importDefault(require("lodash/isEqual")); const utils_1 = require("../utils"); const react_1 = __importDefault(require("react")); const StateManipulator_1 = __importDefault(require("./StateManipulator")); const emptyDepencencies = []; const defaultState = { errors: {}, touches: {}, isValid: true, loading: false, existsChanges: false, isSubmitted: false, focused: null, submitCount: 0, }; class FormManager { constructor(props) { this.customValidators = {}; this.timeouts = []; this.name = props.name; this.manager = props.manager; this.validateHandler = props.validate; this.onChange = props.onChange; this.onSubmit = props.onSubmit; this.validationSchema = props.validationSchema; this.validateOnMount = props.validateOnMount || false; this.resetOnSubmit = props.resetOnSubmit || false; this.formatState = props.formatState; this.initialState = cloneDeep_1.default(props.initialState); this.initialErrors = cloneDeep_1.default(props.initialErrors) || {}; this.initialTouches = cloneDeep_1.default(props.initialTouches) || {}; this.manipulator = new StateManipulator_1.default(Object.assign(Object.assign({}, props), { defaultState, initialTouches: this.initialTouches, initialErrors: this.initialErrors, customValidators: this.customValidators })); // for set default if (!this.manager.get()) { this.set(Object.assign(Object.assign({}, defaultState), { values: this.initialState, errors: this.initialErrors, touches: this.initialTouches })); } this.validate(this.validateOnMount); const timeout = setTimeout(() => { this.validate(this.validateOnMount); if (props.onInit) { props.onInit(this); } }); this.timeouts.push(timeout); } set(state) { return this.manager.set(state); } get() { let data = this.manager.get(); if (!data) { this.manager.set(Object.assign(Object.assign({}, defaultState), { values: this.initialState, errors: this.initialErrors, touches: this.initialTouches })); data = this.manager.get(); } return cloneDeep_1.default(data); } exists() { try { const data = this.manager.get(); return Boolean(data); } catch (e) { return false; } } useState(selector = ((s) => s), dependencies = emptyDepencencies) { const fullState = this.get(); const [state, setState] = react_1.default.useState(selector ? selector(fullState) : fullState); react_1.default.useEffect(() => { const nextState = selector ? selector(fullState) : fullState; if (JSON.stringify(state) !== JSON.stringify(nextState)) { setState(nextState); } return this.watch(selector, s => setState(s)); }, [selector, ...dependencies]); return state; } watch(selector, handler) { return this.manager.watch(selector, handler, (selector ? selector(this.get()) : this.get())); } useValue(key) { const watcher = react_1.default.useCallback(state => { return this.manipulator.getValue(state, key); }, [key]); const value = this.useState(watcher, [key]); return value; } useTouched(key) { const watcher = react_1.default.useCallback(state => { return this.manipulator.getTouched(state, key); }, [key]); const value = this.useState(watcher, [key]); return value; } useError(key) { const watcher = react_1.default.useCallback(state => { return this.manipulator.getError(state, key); }, [key]); const value = this.useState(watcher, [key]); return value; } setValues(values) { const prev = Object.assign({}, this.get()); const next = Object.assign(Object.assign({}, prev), { values }); const event = { type: 'all', value: next.values }; if (this.formatState) { next.values = this.formatState({ next: next.values, prev: prev.values, event }); } if (!isEqual_1.default(this.initialState, prev.values)) { next.existsChanges = true; } else { next.existsChanges = false; } this.set(next); if (this.onChange) { this.onChange(next.values, prev.values, this, event); } } setErrors(errors) { return this.set(Object.assign(Object.assign({}, this.get()), { errors })); } setTouches(touches) { return this.set(Object.assign(Object.assign({}, this.get()), { touches })); } setFieldValue(key, newValue) { let state = this.get(); const prevValues = cloneDeep_1.default(state.values); const touched = utils_1.getDeepStatus(state.touches, key); const event = { type: 'field', key, value: newValue }; if (!touched) { this.manipulator.setTouched(state, key, true); } this.manipulator.setValue(state, key, newValue); if (this.formatState) { state.values = this.formatState({ next: state.values, prev: prevValues, event }); } this.manipulator.validate(state, false); if (!isEqual_1.default(this.initialState, state.values)) { state.existsChanges = true; } else { state.existsChanges = false; } this.set(state); if (this.onChange) { this.onChange(state.values, prevValues, this, event); } return state; } setFieldError(key, error) { const state = this.get(); this.manipulator.setError(state, key, error); const nextIsValid = !Boolean(utils_1.firstError(state.errors)); state.isValid = nextIsValid; return this.set(state); } setFieldTouched(key, value) { const state = this.get(); this.manipulator.setTouched(state, key, value); state.focused = null; return this.set(state); } setFieldFocused(key) { const state = this.get(); state.focused = key; return this.set(state); } setIsValid(value) { const state = this.get(); state.isValid = value; return this.set(state); } setIsSubmitted(value) { const state = this.get(); state.isSubmitted = value; return this.set(state); } setExistsChanges(value) { const state = this.get(); state.existsChanges = value; return this.set(state); } setLoading(value) { const state = this.get(); state.loading = value; return this.set(state); } validate(allTouched) { const state = this.get(); this.manipulator.validate(state, allTouched); this.set(state); } addFieldValidator(key, func) { if (!this.customValidators[key]) { this.customValidators[key] = func; } } removeFieldValidator(key) { delete this.customValidators[key]; } submit() { const state = this.get(); this.manipulator.validate(state, true); state.isSubmitted = true; if (this.onSubmit && state.isValid) { state.loading = true; state.submitCount++; this.set(state); return this.onSubmit(state, this) .then(s => { const state2 = this.get(); if (this.resetOnSubmit) { this.manipulator.reset(state2); } state2.loading = false; this.set(state2); return s; }) .catch((err) => { const state2 = this.get(); state2.loading = false; this.set(state2); return err; }); } else { this.set(state); return Promise.resolve(); } } reset(getState) { const state = this.get(); this.manipulator.reset(state, getState); this.manipulator.validate(state, this.validateOnMount); state.isSubmitted = false; state.existsChanges = false; state.responseMessage = undefined; this.initialState = state.values; this.set(state); } responseMessage(message) { const state = this.get(); state.responseMessage = message; this.set(state); } getInitialState() { return this.initialState; } renewOnChange(handler) { this.onChange = handler; } renewOnSubmit(handler) { this.onSubmit = handler; } stopTimeouts() { this.timeouts.forEach(clearTimeout); this.timeouts = []; } } exports.default = FormManager;