mui-extended
Version:
Extended UI Components built on Material UI
208 lines (207 loc) • 9.14 kB
JavaScript
import { __awaiter, __extends, __generator } from "tslib";
import { jsx as _jsx } from "react/jsx-runtime";
import { validate } from "decorated-ajv";
import { cloneDeep } from "lodash";
import { Component } from "react";
import { FormContext } from "./FormContext";
import { debugEvent } from "./debug";
var getDefaultValidator = function (schema) {
return function (name, value) { return __awaiter(void 0, void 0, void 0, function () {
var violations;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, validate(schema, value)];
case 1:
violations = _a.sent();
if (violations.length > 0) {
throw new Error(violations[0].message);
}
return [2 /*return*/];
}
});
}); };
};
var Form = /** @class */ (function (_super) {
__extends(Form, _super);
function Form(props) {
var _this = _super.call(this, props) || this;
_this.validationErrors = {};
_this.onFieldBlur = _this.onFieldBlur.bind(_this);
_this.onFieldChange = _this.onFieldChange.bind(_this);
_this.submit = _this.submit.bind(_this);
_this.reset = _this.reset.bind(_this);
_this._validateField = _this._validateField.bind(_this);
_this._validateWrapper = _this._validateWrapper.bind(_this);
_this.validateField = _this.validateField.bind(_this);
_this.validate = _this.validate.bind(_this);
_this._getInitialState = _this._getInitialState.bind(_this);
_this.state = _this._getInitialState();
return _this;
}
Form.prototype._getInitialState = function () {
return {
values: cloneDeep(this.props.initialValues),
errors: cloneDeep(this.props.initialErrors || {}),
touched: {},
isDirty: false,
isSubmitting: false,
isValid: true,
onFieldBlur: this.onFieldBlur,
onFieldChange: this.onFieldChange,
submit: this.submit,
reset: this.reset
};
};
Form.prototype.onFieldBlur = function (name) {
var _this = this;
var touched = cloneDeep(this.state.touched);
touched[name] = true;
this.setState({ isDirty: true, touched: touched });
setTimeout(function () {
// delay the validation
_this.validateField(name);
}, 10);
};
Form.prototype.onFieldChange = function (name, value) {
var values = cloneDeep(this.state.values);
values[name] = value;
this.setState({ values: values });
};
Form.prototype._validateField = function (name) {
return __awaiter(this, void 0, void 0, function () {
var validator, e_1, errorMessage;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
debugEvent("_validateField", "start " + (name && name.toLocaleString()));
validator = this.props.validators && this.props.validators[name]
? this.props.validators[name]
: this.props.schemas && this.props.schemas[name]
? getDefaultValidator(this.props.schemas[name])
: undefined;
if (!validator) return [3 /*break*/, 4];
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, validator(name, this.state.values[name])];
case 2:
_a.sent();
delete this.validationErrors[name];
return [3 /*break*/, 4];
case 3:
e_1 = _a.sent();
errorMessage = e_1.message;
/***
* TODO: handle error message properly here, for better readability
*/
this.validationErrors[name] = errorMessage;
return [3 /*break*/, 4];
case 4:
debugEvent("_validateField", "end " + (name && name.toLocaleString()));
return [2 /*return*/];
}
});
});
};
Form.prototype._validateWrapper = function (validator) {
return __awaiter(this, void 0, void 0, function () {
var result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
debugEvent("_validateWrapper", "start");
return [4 /*yield*/, validator()];
case 1:
result = _a.sent();
this.setState({
errors: this.validationErrors,
isValid: Object.keys(this.validationErrors).length == 0
});
debugEvent("_validateWrapper", "end");
return [2 /*return*/, result];
}
});
});
};
Form.prototype.validateField = function (name) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this._validateWrapper(function () { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this._validateField(name)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); })];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
Form.prototype.validate = function () {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
debugEvent("validate", "start");
return [4 /*yield*/, this._validateWrapper(function () { return __awaiter(_this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Promise.allSettled(Object.keys(this.state.values).map(function (name) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this._validateField(name)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); }))];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); })];
case 1:
_a.sent();
debugEvent("validate", "end");
return [2 /*return*/];
}
});
});
};
Form.prototype.reset = function () {
this.setState(this._getInitialState());
};
Form.prototype.submit = function () {
var _this = this;
setTimeout(function () {
// delay the submit
_this.setState({ isSubmitting: true });
_this.validate()
.then(function () {
if (_this.state.isValid) {
return _this.props.onSubmit(_this.state.values);
}
})
.finally(function () {
_this.setState({ isSubmitting: false });
});
}, 10);
};
Form.prototype.render = function () {
return (_jsx(FormContext.Provider, { value: this.state, children: this.props.children }));
};
return Form;
}(Component));
export { Form };