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
JavaScript
"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);
};