UNPKG

form-studio

Version:

A tool that helps design, create and manage form / survey / questionnaire through simple JSON configurations.

748 lines (747 loc) 38.2 kB
"use strict"; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _Form_instances, _Form_onFormUpdate, _Form_validators, _Form_configs, _Form_defaultAnswers, _Form_groupById, _Form_questionById, _Form_choiceById, _Form_parentGroupByGroupId, _Form_groupByQuestionId, _Form_questionByChoiceId, _Form_currentAnswerByQuestionId, _Form_validatedAnswerByQuestionId, _Form_validatingByQuestionId, _Form_errorByQuestionId, _Form_disabledByChoicesById, _Form_enabledByChoicesById, _Form_processGroups, _Form_processQuestions, _Form_processChoices, _Form_toGroupRenderInstructions, _Form_toQuestionRenderInstructions, _Form_toChoiceRenderInstructions, _Form_findGroup, _Form_findQuestion, _Form_findChoice, _Form_internalClearGroup, _Form_internalClearAnswer, _Form_internalResetGroup, _Form_internalResetAnswer, _Form_internalImportAnswers, _Form_getValidators, _Form_executeValidators, _Form_setCurrentAnswerAndValidate, _Form_internalSetAnswer, _Form_internalSetAny, _Form_internalSetChoice, _Form_internalSetChoices, _Form_internalSelectChoice, _Form_isChoiceSelected, _Form_isItemDisabled, _Form_isGroupDisabled, _Form_isQuestionDisabled, _Form_isChoiceDisabled, _Form_endByInformFormUpdate, _Form_informFormUpdate; Object.defineProperty(exports, "__esModule", { value: true }); exports.Form = void 0; const ConfigsSanitizers_1 = require("./ConfigsSanitizers"); const ConfigsValidator_1 = require("./ConfigsValidator"); /** * @category Form */ class Form { /** * Construct a form. * * @param configs configs * @param options options * @throws if configs is invalid */ constructor(configs, options) { _Form_instances.add(this); _Form_onFormUpdate.set(this, void 0); _Form_validators.set(this, {}); _Form_configs.set(this, void 0); _Form_defaultAnswers.set(this, {}); _Form_groupById.set(this, new Map()); _Form_questionById.set(this, new Map()); _Form_choiceById.set(this, new Map()); _Form_parentGroupByGroupId.set(this, new Map()); _Form_groupByQuestionId.set(this, new Map()); _Form_questionByChoiceId.set(this, new Map()); _Form_currentAnswerByQuestionId.set(this, new Map()); _Form_validatedAnswerByQuestionId.set(this, new Map()); _Form_validatingByQuestionId.set(this, new Map()); _Form_errorByQuestionId.set(this, new Map()); _Form_disabledByChoicesById.set(this, new Map()); _Form_enabledByChoicesById.set(this, new Map()); __classPrivateFieldSet(this, _Form_configs, (0, ConfigsSanitizers_1.sanitizeConfigs)(configs), "f"); const result = new ConfigsValidator_1.ConfigsValidator().validate(__classPrivateFieldGet(this, _Form_configs, "f"), false); if (!result.valid) { throw new Error('Invalid configs. You may use validateConfigs method to see what is wrong.'); } this.setValidators(options?.validators); this.setUpdateListener(options?.onFormUpdate); __classPrivateFieldGet(this, _Form_instances, "m", _Form_processGroups).call(this, undefined, __classPrivateFieldGet(this, _Form_configs, "f").groups); __classPrivateFieldGet(this, _Form_instances, "m", _Form_processQuestions).call(this, undefined, __classPrivateFieldGet(this, _Form_configs, "f").questions); __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalImportAnswers).call(this, __classPrivateFieldGet(this, _Form_defaultAnswers, "f"), options); }); } setValidators(validators) { __classPrivateFieldSet(this, _Form_validators, validators ?? {}, "f"); } setUpdateListener(onFormUpdate) { __classPrivateFieldSet(this, _Form_onFormUpdate, onFormUpdate, "f"); } /** * Get sanitized configs of this form. * * You can persist it and use it to reconstruct the form later. * * @returns configs */ getConfigs() { return __classPrivateFieldGet(this, _Form_configs, "f"); } /** * Get a set of instructions to be used for rendering frontend UI. * * @returns render instructions */ getRenderInstructions() { const groups = __classPrivateFieldGet(this, _Form_instances, "m", _Form_toGroupRenderInstructions).call(this, __classPrivateFieldGet(this, _Form_configs, "f").groups); const questions = __classPrivateFieldGet(this, _Form_instances, "m", _Form_toQuestionRenderInstructions).call(this, __classPrivateFieldGet(this, _Form_configs, "f").questions); const validating = groups.some(group => group.validating) || questions.some(question => question.validating); return { validating, groups, questions }; } /** * Clear answers of the entire form. * * @param options options */ clear(options) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { for (const group of __classPrivateFieldGet(this, _Form_configs, "f").groups) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalClearGroup).call(this, group.id, options); } }); } /** * Clear answers of the entire group. * * @param groupId group id * @param options options */ clearGroup(groupId, options) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalClearGroup).call(this, groupId, options); }); } /** * Clear answer of a question. * * @param questionId question id * @param options options */ clearAnswer(questionId, options) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalClearAnswer).call(this, questionId, options); }); } /** * Reset answers of the entire form to default answers. * * @param options options */ reset(options) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { for (const group of __classPrivateFieldGet(this, _Form_configs, "f").groups) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalResetGroup).call(this, group.id, options); } }); } /** * Reset answers of the entire group to default answers. * * @param groupId group id * @param options options */ resetGroup(groupId, options) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalResetGroup).call(this, groupId, options); }); } /** * Reset answer of a question to default answer. * * @param questionId question id * @param options options */ resetAnswer(questionId, options) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalResetAnswer).call(this, questionId, options); }); } /** * Import answers to the form. * * @param answers answers * @param options options */ importAnswers(answers, options) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalImportAnswers).call(this, answers, options); }); } /** * Set answer of a question. * * @param questionId question id * @param answer answer * @param options options */ setAnswer(questionId, answer, options) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSetAnswer).call(this, questionId, answer, options); }); } /** * Set answer of a question with `any` as [[type]]. * * @param questionId question id * @param answer answer * @param options options */ setAny(questionId, answer, options) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSetAny).call(this, questionId, answer, options); }); } /** * Set answer of a question with `choice` as [[type]]. * * @param questionId question id * @param value choice's value * @param options options */ setChoice(questionId, value, options) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSetChoice).call(this, questionId, value, options); }); } /** * Set answers of a question with `choices` as [[type]]. * * @param questionId question id * @param values choices' values * @param options options */ setChoices(questionId, values, options) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSetChoices).call(this, questionId, values, options); }); } /** * Select invididual choice. * * This method can be used by questions with `choice` or `choices` as [[type]] only. * * @param choiceId choice id * @param selected selected/unselected * @param options options */ selectChoice(choiceId, selected, options) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSelectChoice).call(this, choiceId, selected, options); }); } /** * Get current answer of a question. The answer is unvalidated. * * @param questionId question id * @returns current answer */ getCurrentAnswer(questionId) { return __classPrivateFieldGet(this, _Form_currentAnswerByQuestionId, "f").get(questionId); } /** * Get current answers. The answers are unvalidated. * * You can persist it and use it with [[importAnswers]] method to restore the answers later. * * @returns current answers */ getCurrentAnswers() { const answers = {}; for (const [questionId] of __classPrivateFieldGet(this, _Form_questionById, "f").entries()) { const answer = __classPrivateFieldGet(this, _Form_currentAnswerByQuestionId, "f").get(questionId); if (answer !== undefined) { answers[questionId] = answer; } } return answers; } /** * Get validated answer of a question. * * If the question is disabled or it's answer is not valid, it's answer will be set to `undefined`. * * @param questionId question id * @returns validated answer */ getValidatedAnswer(questionId) { return __classPrivateFieldGet(this, _Form_validatedAnswerByQuestionId, "f").get(questionId); } /** * Get validated answers. * * If a question is disabled or it's answer is not valid, it's answer will be set to `undefined`. * * You can persist it and use it with [[importAnswers]] method to restore the answers later. * * @returns validated answers */ getValidatedAnswers() { const answers = {}; for (const [questionId, question] of __classPrivateFieldGet(this, _Form_questionById, "f").entries()) { if (!__classPrivateFieldGet(this, _Form_instances, "m", _Form_isQuestionDisabled).call(this, question)) { const answer = __classPrivateFieldGet(this, _Form_validatedAnswerByQuestionId, "f").get(questionId); if (answer !== undefined) { answers[questionId] = answer; } } } return answers; } /** * Get error of a question. * * If the question hasn't gone through validation, it will not have error, even if its answer is currently invalid. * * @param questionId question id * @returns error */ getError(questionId) { return __classPrivateFieldGet(this, _Form_errorByQuestionId, "f").get(questionId); } /** * Get errors. * * Questions which didn't go through validation will not have errors, even if their answers are currently invalid. * * You can use [[validate]] method to validate all answers in the form. * * @returns errors */ getErrors() { const errors = {}; for (const [questionId, question] of __classPrivateFieldGet(this, _Form_questionById, "f").entries()) { if (!__classPrivateFieldGet(this, _Form_instances, "m", _Form_isQuestionDisabled).call(this, question)) { const error = __classPrivateFieldGet(this, _Form_errorByQuestionId, "f").get(questionId); if (error !== undefined) { errors[questionId] = error; } } } return errors; } /** * Check whether form is currently being validated. * * The result might be `true` if you have async validator and the validation is not completed yet. * * @returns whether form is current being validated */ isValidating() { for (const validating of __classPrivateFieldGet(this, _Form_validatingByQuestionId, "f").values()) { if (validating) { return true; } } return false; } /** * Check whether form is clean. * * Form will always be clean if it didn't go through any validation, even if there are invalid answers in the form. * * You can use [[validate]] method to validate all answers in the form. * * @returns whether form is clean */ isClean() { for (const [questionId, error] of __classPrivateFieldGet(this, _Form_errorByQuestionId, "f").entries()) { const question = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findQuestion).call(this, questionId); if (__classPrivateFieldGet(this, _Form_instances, "m", _Form_isQuestionDisabled).call(this, question)) { continue; } if (error) { return false; } } return true; } /** * Do a final round of validation and get the validated answers. * * This method will not update render instructions. * It is more for when you need to make sure that the form is really clean and get the final validated answers for further usage, * e.g. calling API, store into database, etc. * * @returns validated answer or `false` if form is not clean */ async asyncValidate() { const form = new Form(this.getConfigs(), { validators: __classPrivateFieldGet(this, _Form_validators, "f") }); form.importAnswers(this.getCurrentAnswers()); while (true) { if (form.isValidating()) { await new Promise(resolve => setTimeout(resolve, 10)); } else { break; } } if (form.isClean()) { return form.getValidatedAnswers(); } return false; } /** * Validate the entire form. * * @returns whether form is clean */ validate() { return __classPrivateFieldGet(this, _Form_instances, "m", _Form_endByInformFormUpdate).call(this, () => { const answers = this.getCurrentAnswers(); __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalImportAnswers).call(this, answers); }); } /** * Validate configs. * * The following validations will be conducted: * - Form is not without any groups or questions * - No duplicated ids within the form * - No groups without questions * - No questions with `choice` or `choices` as type without choices * - No duplicated choice values within a question * - No circular choices' `onSelected` configs * * Put `strict` as `true` to validate the following: * - No unrecognized ids in choices' `onSelected` configs * * @param configs configs * @param strict strict * @returns validation result */ static validateConfigs(configs, strict = false) { const sanitizedconfigs = (0, ConfigsSanitizers_1.sanitizeConfigs)(configs); return new ConfigsValidator_1.ConfigsValidator().validate(sanitizedconfigs, strict); } } exports.Form = Form; _Form_onFormUpdate = new WeakMap(), _Form_validators = new WeakMap(), _Form_configs = new WeakMap(), _Form_defaultAnswers = new WeakMap(), _Form_groupById = new WeakMap(), _Form_questionById = new WeakMap(), _Form_choiceById = new WeakMap(), _Form_parentGroupByGroupId = new WeakMap(), _Form_groupByQuestionId = new WeakMap(), _Form_questionByChoiceId = new WeakMap(), _Form_currentAnswerByQuestionId = new WeakMap(), _Form_validatedAnswerByQuestionId = new WeakMap(), _Form_validatingByQuestionId = new WeakMap(), _Form_errorByQuestionId = new WeakMap(), _Form_disabledByChoicesById = new WeakMap(), _Form_enabledByChoicesById = new WeakMap(), _Form_instances = new WeakSet(), _Form_processGroups = function _Form_processGroups(parentGroup, groups) { groups.forEach(group => { __classPrivateFieldGet(this, _Form_groupById, "f").set(group.id, group); __classPrivateFieldGet(this, _Form_instances, "m", _Form_processGroups).call(this, group, group.groups ?? []); __classPrivateFieldGet(this, _Form_instances, "m", _Form_processQuestions).call(this, group, group.questions ?? []); if (parentGroup) { __classPrivateFieldGet(this, _Form_parentGroupByGroupId, "f").set(group.id, parentGroup); } }); }, _Form_processQuestions = function _Form_processQuestions(group, questions) { questions.forEach(question => { __classPrivateFieldGet(this, _Form_questionById, "f").set(question.id, question); if (group) { __classPrivateFieldGet(this, _Form_groupByQuestionId, "f").set(question.id, group); } if (question.type !== 'any') { __classPrivateFieldGet(this, _Form_instances, "m", _Form_processChoices).call(this, question, question.choices); } if (!!question.defaultAnswer) { __classPrivateFieldGet(this, _Form_defaultAnswers, "f")[question.id] = question.defaultAnswer; } }); }, _Form_processChoices = function _Form_processChoices(question, choices) { choices.forEach(choice => { __classPrivateFieldGet(this, _Form_choiceById, "f").set(choice.id, choice); __classPrivateFieldGet(this, _Form_questionByChoiceId, "f").set(choice.id, question); choice.onSelected?.disable?.forEach(id => { let disabledByChoices = __classPrivateFieldGet(this, _Form_disabledByChoicesById, "f").get(id); if (!disabledByChoices) { disabledByChoices = []; } disabledByChoices.push(choice); __classPrivateFieldGet(this, _Form_disabledByChoicesById, "f").set(id, disabledByChoices); }); choice.onSelected?.enable?.forEach(id => { let enabledByChoices = __classPrivateFieldGet(this, _Form_enabledByChoicesById, "f").get(id); if (!enabledByChoices) { enabledByChoices = []; } enabledByChoices.push(choice); __classPrivateFieldGet(this, _Form_enabledByChoicesById, "f").set(id, enabledByChoices); }); }); }, _Form_toGroupRenderInstructions = function _Form_toGroupRenderInstructions(groups) { return groups.map((group) => { const groups = __classPrivateFieldGet(this, _Form_instances, "m", _Form_toGroupRenderInstructions).call(this, group.groups); const questions = __classPrivateFieldGet(this, _Form_instances, "m", _Form_toQuestionRenderInstructions).call(this, group.questions); const validating = groups.some(group => group.validating) || questions.some(question => question.validating); return { id: group.id, disabled: __classPrivateFieldGet(this, _Form_instances, "m", _Form_isGroupDisabled).call(this, group), custom: group.custom, validating, groups, questions }; }); }, _Form_toQuestionRenderInstructions = function _Form_toQuestionRenderInstructions(questions) { return questions.map((question) => ({ id: question.id, disabled: __classPrivateFieldGet(this, _Form_instances, "m", _Form_isQuestionDisabled).call(this, question), custom: question.custom, type: question.type, choices: question.type !== 'any' ? __classPrivateFieldGet(this, _Form_instances, "m", _Form_toChoiceRenderInstructions).call(this, question.choices) : [], currentAnswer: __classPrivateFieldGet(this, _Form_currentAnswerByQuestionId, "f").get(question.id), validatedAnswer: __classPrivateFieldGet(this, _Form_instances, "m", _Form_isQuestionDisabled).call(this, question) ? undefined : __classPrivateFieldGet(this, _Form_validatedAnswerByQuestionId, "f").get(question.id), validating: !!__classPrivateFieldGet(this, _Form_validatingByQuestionId, "f").get(question.id), error: __classPrivateFieldGet(this, _Form_errorByQuestionId, "f").get(question.id) })); }, _Form_toChoiceRenderInstructions = function _Form_toChoiceRenderInstructions(choices) { return choices.map((choice) => ({ id: choice.id, disabled: __classPrivateFieldGet(this, _Form_instances, "m", _Form_isChoiceDisabled).call(this, choice), custom: choice.custom, value: choice.value })); }, _Form_findGroup = function _Form_findGroup(groupId) { const group = __classPrivateFieldGet(this, _Form_groupById, "f").get(groupId); if (!group) { throw new Error('Group is not found.'); } return group; }, _Form_findQuestion = function _Form_findQuestion(questionId) { const question = __classPrivateFieldGet(this, _Form_questionById, "f").get(questionId); if (!question) { throw new Error('Question is not found.'); } return question; }, _Form_findChoice = function _Form_findChoice(choiceId) { const choice = __classPrivateFieldGet(this, _Form_choiceById, "f").get(choiceId); if (!choice) { throw new Error('Choice is not found.'); } return choice; }, _Form_internalClearGroup = function _Form_internalClearGroup(groupId, options) { const group = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findGroup).call(this, groupId); for (const subGroup of group.groups) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalClearGroup).call(this, subGroup.id, options); } for (const question of group.questions) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalClearAnswer).call(this, question.id, options); } }, _Form_internalClearAnswer = function _Form_internalClearAnswer(questionId, options) { const question = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findQuestion).call(this, questionId); __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSetAnswer).call(this, question.id, undefined, options); }, _Form_internalResetGroup = function _Form_internalResetGroup(groupId, options) { const group = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findGroup).call(this, groupId); for (const subGroup of group.groups) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalResetGroup).call(this, subGroup.id, options); } for (const question of group.questions) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalResetAnswer).call(this, question.id, options); } }, _Form_internalResetAnswer = function _Form_internalResetAnswer(questionId, options) { const question = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findQuestion).call(this, questionId); const defaultAnswer = __classPrivateFieldGet(this, _Form_defaultAnswers, "f")[questionId]; __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSetAnswer).call(this, question.id, defaultAnswer, options); }, _Form_internalImportAnswers = function _Form_internalImportAnswers(answers, options) { for (const questionId of __classPrivateFieldGet(this, _Form_questionById, "f").keys()) { const answer = answers[questionId]; __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSetAnswer).call(this, questionId, answer, options); } }, _Form_getValidators = function _Form_getValidators(names) { const validators = []; for (const name of names) { const validator = __classPrivateFieldGet(this, _Form_validators, "f")[name]; if (validator) { validators.push(validator); } } return validators; }, _Form_executeValidators = function _Form_executeValidators(validators, question, answer, previousAnswer) { const validator = validators.shift(); if (!validator) { return; } const validationResult = validator(answer, question, previousAnswer, this); if (validationResult instanceof Promise) { return validationResult.then(() => __classPrivateFieldGet(this, _Form_instances, "m", _Form_executeValidators).call(this, validators, question, answer, previousAnswer)); } return __classPrivateFieldGet(this, _Form_instances, "m", _Form_executeValidators).call(this, validators, question, answer, previousAnswer); }, _Form_setCurrentAnswerAndValidate = function _Form_setCurrentAnswerAndValidate(question, answer, options) { const previousAnswer = __classPrivateFieldGet(this, _Form_currentAnswerByQuestionId, "f").get(question.id); __classPrivateFieldGet(this, _Form_currentAnswerByQuestionId, "f").set(question.id, answer); if (question.type === 'choice') { const choice = question.choices.find(choice => choice.value === answer); if (choice && __classPrivateFieldGet(this, _Form_instances, "m", _Form_isChoiceDisabled).call(this, choice)) { answer = undefined; } } else if (question.type === 'choices') { let choices = question.choices.filter(choice => answer.includes(choice.value)); choices = choices.filter(choice => !__classPrivateFieldGet(this, _Form_instances, "m", _Form_isChoiceDisabled).call(this, choice)); answer = choices.map(choice => choice.value); } __classPrivateFieldGet(this, _Form_currentAnswerByQuestionId, "f").set(question.id, answer); const onSuccess = () => { __classPrivateFieldGet(this, _Form_validatedAnswerByQuestionId, "f").set(question.id, answer); __classPrivateFieldGet(this, _Form_errorByQuestionId, "f").delete(question.id); }; const onError = (err) => { __classPrivateFieldGet(this, _Form_validatedAnswerByQuestionId, "f").delete(question.id); __classPrivateFieldGet(this, _Form_errorByQuestionId, "f").set(question.id, err); }; const validators = __classPrivateFieldGet(this, _Form_instances, "m", _Form_getValidators).call(this, question.validators); if (!validators.length) { onSuccess(); return; } if (options?.validate === false) { __classPrivateFieldGet(this, _Form_validatedAnswerByQuestionId, "f").delete(question.id); __classPrivateFieldGet(this, _Form_errorByQuestionId, "f").delete(question.id); return; } let validationResult; try { validationResult = __classPrivateFieldGet(this, _Form_instances, "m", _Form_executeValidators).call(this, validators, question, answer, previousAnswer); } catch (err) { onError(err); return; } if (validationResult instanceof Promise) { __classPrivateFieldGet(this, _Form_validatingByQuestionId, "f").set(question.id, true); validationResult .then(onSuccess) .catch(onError) .finally(() => { __classPrivateFieldGet(this, _Form_validatingByQuestionId, "f").delete(question.id); __classPrivateFieldGet(this, _Form_instances, "m", _Form_informFormUpdate).call(this); }); return; } onSuccess(); }, _Form_internalSetAnswer = function _Form_internalSetAnswer(questionId, answer, options) { const question = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findQuestion).call(this, questionId); if (question.type === 'any') { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSetAny).call(this, question.id, answer, options); } else if (question.type === 'choice') { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSetChoice).call(this, question.id, answer, options); } else if (question.type === 'choices') { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSetChoices).call(this, question.id, answer ?? [], options); } }, _Form_internalSetAny = function _Form_internalSetAny(questionId, answer, options) { const question = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findQuestion).call(this, questionId); if (question.type !== 'any') { throw new Error("Question type is not 'any'."); } __classPrivateFieldGet(this, _Form_instances, "m", _Form_setCurrentAnswerAndValidate).call(this, question, answer, options); }, _Form_internalSetChoice = function _Form_internalSetChoice(questionId, value, options) { const question = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findQuestion).call(this, questionId); if (question.type !== 'choice') { throw new Error("Question type is not 'choice'."); } const choice = question.choices.find(choice => choice.value === value); __classPrivateFieldGet(this, _Form_instances, "m", _Form_setCurrentAnswerAndValidate).call(this, question, choice?.value, options); }, _Form_internalSetChoices = function _Form_internalSetChoices(questionId, values, options) { const question = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findQuestion).call(this, questionId); if (question.type !== 'choices') { throw new Error("Question type is not 'choices'."); } const choices = question.choices.filter(choice => values.includes(choice.value)); __classPrivateFieldGet(this, _Form_instances, "m", _Form_setCurrentAnswerAndValidate).call(this, question, choices.map(choice => choice.value), options); }, _Form_internalSelectChoice = function _Form_internalSelectChoice(choiceId, selected, options) { const choice = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findChoice).call(this, choiceId); const question = __classPrivateFieldGet(this, _Form_questionByChoiceId, "f").get(choiceId); let currentAnswer = __classPrivateFieldGet(this, _Form_currentAnswerByQuestionId, "f").get(question.id); if (question.type === 'choice') { if (selected) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSetChoice).call(this, question.id, choice.value, options); } else if (choice.value === currentAnswer) { __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSetChoice).call(this, question.id, undefined, options); } } else if (question.type === 'choices') { currentAnswer = currentAnswer ?? []; currentAnswer = currentAnswer.filter(value => value !== choice.value); if (selected) { currentAnswer.push(choice.value); } __classPrivateFieldGet(this, _Form_instances, "m", _Form_internalSetChoices).call(this, question.id, currentAnswer, options); } }, _Form_isChoiceSelected = function _Form_isChoiceSelected(choice) { if (__classPrivateFieldGet(this, _Form_instances, "m", _Form_isChoiceDisabled).call(this, choice)) { return false; } const question = __classPrivateFieldGet(this, _Form_questionByChoiceId, "f").get(choice.id); if (question.type === 'choice') { const answer = __classPrivateFieldGet(this, _Form_currentAnswerByQuestionId, "f").get(question.id); return choice.value === answer; } if (question.type === 'choices') { const answer = __classPrivateFieldGet(this, _Form_currentAnswerByQuestionId, "f").get(question.id); return !!answer?.includes(choice.value); } return false; }, _Form_isItemDisabled = function _Form_isItemDisabled(item) { if (item.disabledOnSelected) { for (const condition of item.disabledOnSelected) { if (Array.isArray(condition)) { if (condition.every(choiceId => { const choice = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findChoice).call(this, choiceId); return __classPrivateFieldGet(this, _Form_instances, "m", _Form_isChoiceSelected).call(this, choice); })) { return true; } } else { const choice = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findChoice).call(this, condition); if (__classPrivateFieldGet(this, _Form_instances, "m", _Form_isChoiceSelected).call(this, choice)) { return true; } } } } if (item.enabledOnSelected) { for (const condition of item.enabledOnSelected) { if (Array.isArray(condition)) { if (condition.every(choiceId => { const choice = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findChoice).call(this, choiceId); return __classPrivateFieldGet(this, _Form_instances, "m", _Form_isChoiceSelected).call(this, choice); })) { return false; } } else { const choice = __classPrivateFieldGet(this, _Form_instances, "m", _Form_findChoice).call(this, condition); if (__classPrivateFieldGet(this, _Form_instances, "m", _Form_isChoiceSelected).call(this, choice)) { return false; } } } } const disabledByChoices = __classPrivateFieldGet(this, _Form_disabledByChoicesById, "f").get(item.id) ?? []; for (const choice of disabledByChoices) { if (__classPrivateFieldGet(this, _Form_instances, "m", _Form_isChoiceSelected).call(this, choice)) { return true; } } const enabledByChoices = __classPrivateFieldGet(this, _Form_enabledByChoicesById, "f").get(item.id) ?? []; for (const choice of enabledByChoices) { if (__classPrivateFieldGet(this, _Form_instances, "m", _Form_isChoiceSelected).call(this, choice)) { return false; } } return item.defaultDisabled; }, _Form_isGroupDisabled = function _Form_isGroupDisabled(group) { const parentGroup = __classPrivateFieldGet(this, _Form_parentGroupByGroupId, "f").get(group.id); if (parentGroup && __classPrivateFieldGet(this, _Form_instances, "m", _Form_isGroupDisabled).call(this, parentGroup)) { return true; } return __classPrivateFieldGet(this, _Form_instances, "m", _Form_isItemDisabled).call(this, group); }, _Form_isQuestionDisabled = function _Form_isQuestionDisabled(question) { const group = __classPrivateFieldGet(this, _Form_groupByQuestionId, "f").get(question.id); if (group && __classPrivateFieldGet(this, _Form_instances, "m", _Form_isGroupDisabled).call(this, group)) { return true; } return __classPrivateFieldGet(this, _Form_instances, "m", _Form_isItemDisabled).call(this, question); }, _Form_isChoiceDisabled = function _Form_isChoiceDisabled(choice) { const question = __classPrivateFieldGet(this, _Form_questionByChoiceId, "f").get(choice.id); if (__classPrivateFieldGet(this, _Form_instances, "m", _Form_isQuestionDisabled).call(this, question)) { return true; } return __classPrivateFieldGet(this, _Form_instances, "m", _Form_isItemDisabled).call(this, choice); }, _Form_endByInformFormUpdate = function _Form_endByInformFormUpdate(action) { const result = action(); __classPrivateFieldGet(this, _Form_instances, "m", _Form_informFormUpdate).call(this); return result; }, _Form_informFormUpdate = function _Form_informFormUpdate() { __classPrivateFieldGet(this, _Form_onFormUpdate, "f")?.call(this, this); };