react-form-with-constraints
Version:
Simple form validation for React
141 lines (140 loc) • 6.02 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FormWithConstraints = void 0;
const React = require("react");
const prop_types_1 = require("prop-types");
const assert_1 = require("./assert");
const FieldsStore_1 = require("./FieldsStore");
const InputElement_1 = require("./InputElement");
const notUndefined_1 = require("./notUndefined");
const withFieldDidResetEventEmitter_1 = require("./withFieldDidResetEventEmitter");
const withFieldDidValidateEventEmitter_1 = require("./withFieldDidValidateEventEmitter");
const withFieldWillValidateEventEmitter_1 = require("./withFieldWillValidateEventEmitter");
const withValidateFieldEventEmitter_1 = require("./withValidateFieldEventEmitter");
class FormWithConstraintsComponent extends React.PureComponent {
}
class FormWithConstraints extends (0, withFieldDidResetEventEmitter_1.withFieldDidResetEventEmitter)((0, withFieldWillValidateEventEmitter_1.withFieldWillValidateEventEmitter)((0, withFieldDidValidateEventEmitter_1.withFieldDidValidateEventEmitter)((0, withValidateFieldEventEmitter_1.withValidateFieldEventEmitter)(FormWithConstraintsComponent)))) {
constructor() {
super(...arguments);
this.form = null;
this.fieldsStore = new FieldsStore_1.FieldsStore();
this.fieldFeedbacksKeyCounter = 0;
}
getChildContext() {
return {
form: this
};
}
computeFieldFeedbacksKey() {
return `${this.fieldFeedbacksKeyCounter++}`;
}
validateFields(...inputsOrNames) {
return this._validateFields(true, ...inputsOrNames);
}
validateForm() {
return this.validateFieldsWithoutFeedback();
}
validateFieldsWithoutFeedback(...inputsOrNames) {
return this._validateFields(false, ...inputsOrNames);
}
async _validateFields(forceValidateFields, ...inputsOrNames) {
const fields = new Array();
const inputs = this.normalizeInputs(...inputsOrNames);
for (let i = 0; i < inputs.length; i++) {
const input = inputs[i];
const field = await this.validateField(forceValidateFields, new InputElement_1.InputElement(input), input);
if (field !== undefined)
fields.push(field);
}
return fields;
}
async validateField(forceValidateFields, input, nativeInput) {
const fieldName = input.name;
const field = this.fieldsStore.getField(fieldName);
if (field === undefined) {
}
else if (forceValidateFields || !field.hasFeedbacks()) {
field.element = nativeInput;
field.clearValidations();
this.emitFieldWillValidateEvent(fieldName);
const arrayOfArrays = await this.emitValidateFieldEvent(input);
(0, assert_1.assert)(JSON.stringify(arrayOfArrays.flat(Number.POSITIVE_INFINITY).filter(fieldFeedback => (0, notUndefined_1.notUndefined)(fieldFeedback))) ===
JSON.stringify(field.validations), `FieldsStore does not match emitValidateFieldEvent() result, did the user changed the input rapidly?`);
this.emitFieldDidValidateEvent(field);
}
return field;
}
normalizeInputs(...inputsOrNames) {
let inputs;
if (inputsOrNames.length === 0) {
inputs = Array.from(this.form.querySelectorAll('[name]'));
inputs = inputs.filter(input => input.validity !== undefined);
inputs
.filter(input => input.type !== 'checkbox' && input.type !== 'radio')
.map(input => input.name)
.forEach((name, index, self) => {
if (self.indexOf(name) !== index) {
throw new Error(`Multiple elements matching '[name="${name}"]' inside the form`);
}
});
}
else {
inputs = inputsOrNames.map(input => {
if (typeof input === 'string') {
const query = `[name="${input}"]`;
const elements = Array.from(this.form.querySelectorAll(query));
if (elements.some(el => el.validity === undefined)) {
throw new Error(`'${query}' should match an <input>, <select> or <textarea>`);
}
if (elements.filter(el => el.type !== 'checkbox' && el.type !== 'radio').length > 1) {
throw new Error(`Multiple elements matching '${query}' inside the form`);
}
const element = elements[0];
if (element === undefined) {
throw new Error(`Could not find field '${query}' inside the form`);
}
return element;
}
return input;
});
}
return inputs;
}
isValid() {
return this.fieldsStore.isValid();
}
hasFeedbacks() {
return this.fieldsStore.hasFeedbacks();
}
reset() {
return this.resetFields();
}
resetFields(...inputsOrNames) {
const fields = new Array();
const inputs = this.normalizeInputs(...inputsOrNames);
inputs.forEach(input => {
const field = this.resetField(new InputElement_1.InputElement(input));
if (field !== undefined)
fields.push(field);
});
return fields;
}
resetField(input) {
const fieldName = input.name;
const field = this.fieldsStore.getField(fieldName);
if (field === undefined) {
}
else {
field.clearValidations();
this.emitFieldDidResetEvent(field);
}
return field;
}
render() {
return React.createElement("form", { ref: form => (this.form = form), ...this.props });
}
}
exports.FormWithConstraints = FormWithConstraints;
FormWithConstraints.childContextTypes = {
form: (0, prop_types_1.instanceOf)(FormWithConstraints).isRequired
};