Skip to content

Commit

Permalink
Single-Select Matrix - The required validation error appears immediat…
Browse files Browse the repository at this point in the history
…ely when changing a single row value fix #8727 (#8787)
  • Loading branch information
andrewtelnov authored Sep 9, 2024
1 parent 67c37bf commit fe2e114
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 39 deletions.
15 changes: 6 additions & 9 deletions packages/survey-core/src/question.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2145,7 +2145,7 @@ export class Question extends SurveyElement<Question>
return json;
}
public hasErrors(fireCallback: boolean = true, rec: any = null): boolean {
const errors = this.checkForErrors(!!rec && rec.isOnValueChanged === true);
const errors = this.checkForErrors(!!rec && rec.isOnValueChanged === true, fireCallback);
if (fireCallback) {
if (!!this.survey) {
this.survey.beforeSettingQuestionErrors(this, errors);
Expand Down Expand Up @@ -2206,21 +2206,18 @@ export class Question extends SurveyElement<Question>
var index = errors.indexOf(error);
if (index !== -1) errors.splice(index, 1);
}
private checkForErrors(isOnValueChanged: boolean): Array<SurveyError> {
private checkForErrors(isOnValueChanged: boolean, fireCallback: boolean): Array<SurveyError> {
var qErrors = new Array<SurveyError>();
if (this.isVisible && this.canCollectErrors()) {
this.collectErrors(qErrors, isOnValueChanged);
this.collectErrors(qErrors, isOnValueChanged, fireCallback);
}
return qErrors;
}
protected canCollectErrors(): boolean {
return !this.isReadOnly || settings.readOnly.enableValidation;
}
private collectErrors(
qErrors: Array<SurveyError>,
isOnValueChanged: boolean
) {
this.onCheckForErrors(qErrors, isOnValueChanged);
private collectErrors(qErrors: Array<SurveyError>, isOnValueChanged: boolean, fireCallback: boolean): void {
this.onCheckForErrors(qErrors, isOnValueChanged, fireCallback);
if (qErrors.length > 0 || !this.canRunValidators(isOnValueChanged)) return;
var errors = this.runValidators();
if (errors.length > 0) {
Expand All @@ -2244,7 +2241,7 @@ export class Question extends SurveyElement<Question>
if (this.validateValueCallback) return this.validateValueCallback();
return this.survey ? this.survey.validateQuestion(this) : null;
}
protected onCheckForErrors(errors: Array<SurveyError>, isOnValueChanged: boolean): void {
protected onCheckForErrors(errors: Array<SurveyError>, isOnValueChanged: boolean, fireCallback: boolean): void {
if ((!isOnValueChanged || this.isOldAnswered) && this.hasRequiredError()) {
const err = new AnswerRequiredError(this.requiredErrorText, this);
err.onUpdateErrorTextCallback = (err) => { err.text = this.requiredErrorText; };
Expand Down
11 changes: 4 additions & 7 deletions packages/survey-core/src/question_baseselect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1355,18 +1355,15 @@ export class QuestionSelectBase extends Question {
this.getPropertyByName(propName).visible
);
}
protected onCheckForErrors(
errors: Array<SurveyError>,
isOnValueChanged: boolean
) {
super.onCheckForErrors(errors, isOnValueChanged);
protected onCheckForErrors(errors: Array<SurveyError>, isOnValueChanged: boolean, fireCallback: boolean): void {
super.onCheckForErrors(errors, isOnValueChanged, fireCallback);
if (!this.hasOther || !this.isOtherSelected || this.otherValue
|| isOnValueChanged && !this.prevOtherErrorValue) return;
const otherEmptyError = new OtherEmptyError(this.otherErrorText, this);
otherEmptyError.onUpdateErrorTextCallback = err => { err.text = this.otherErrorText; };
errors.push(otherEmptyError);
}
public setSurveyImpl(value: ISurveyImpl, isLight?: boolean) {
public setSurveyImpl(value: ISurveyImpl, isLight?: boolean): void {
this.isRunningChoices = true;
super.setSurveyImpl(value, isLight);
this.isRunningChoices = false;
Expand All @@ -1375,7 +1372,7 @@ export class QuestionSelectBase extends Question {
this.updateVisibleChoices();
}
}
protected setSurveyCore(value: ISurvey) {
protected setSurveyCore(value: ISurvey): void {
super.setSurveyCore(value);
if (!!value && !!this.choicesFromQuestion) {
this.onVisibleChoicesChanged();
Expand Down
7 changes: 2 additions & 5 deletions packages/survey-core/src/question_checkbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,8 @@ export class QuestionCheckboxModel extends QuestionCheckboxBase {
return val.map((item: any) => this.createItemValue(item));
}
protected getAnswerCorrectIgnoreOrder(): boolean { return true; }
protected onCheckForErrors(
errors: Array<SurveyError>,
isOnValueChanged: boolean
): void {
super.onCheckForErrors(errors, isOnValueChanged);
protected onCheckForErrors(errors: Array<SurveyError>, isOnValueChanged: boolean, fireCallback: boolean): void {
super.onCheckForErrors(errors, isOnValueChanged, fireCallback);
if (isOnValueChanged) return;

if (this.minSelectedChoices > 0 && this.checkMinSelectedChoicesUnreached()) {
Expand Down
4 changes: 2 additions & 2 deletions packages/survey-core/src/question_custom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -642,8 +642,8 @@ export abstract class QuestionCustomModelBase extends Question
super.setNewValue(newValue);
this.updateElementCss();
}
protected onCheckForErrors(errors: Array<SurveyError>, isOnValueChanged: boolean): void {
super.onCheckForErrors(errors, isOnValueChanged);
protected onCheckForErrors(errors: Array<SurveyError>, isOnValueChanged: boolean, fireCallback: boolean): void {
super.onCheckForErrors(errors, isOnValueChanged, fireCallback);
if (!!this.customQuestion) {
const text = this.customQuestion.onGetErrorText(this);
if(!!text) {
Expand Down
8 changes: 2 additions & 6 deletions packages/survey-core/src/question_file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,8 @@ export class QuestionFileModelBase extends Question {
if (!this.survey) return;
this.survey.clearFiles(this, this.name, this.value, null, () => { });
}

protected onCheckForErrors(
errors: Array<SurveyError>,
isOnValueChanged: boolean
) {
super.onCheckForErrors(errors, isOnValueChanged);
protected onCheckForErrors(errors: Array<SurveyError>, isOnValueChanged: boolean, fireCallback: boolean): void {
super.onCheckForErrors(errors, isOnValueChanged, fireCallback);
if (this.isUploading && this.waitForUpload) {
errors.push(
new UploadingFileError(
Expand Down
6 changes: 3 additions & 3 deletions packages/survey-core/src/question_matrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,11 +474,11 @@ export class QuestionMatrixModel
return this.isMouseDown === true && this.hasValuesInAllRows();
}
private errorsInRow: HashTable<boolean>;
protected onCheckForErrors(errors: Array<SurveyError>, isOnValueChanged: boolean): void {
super.onCheckForErrors(errors, isOnValueChanged);
protected onCheckForErrors(errors: Array<SurveyError>, isOnValueChanged: boolean, fireCallback: boolean): void {
super.onCheckForErrors(errors, isOnValueChanged, fireCallback);
if (!isOnValueChanged || this.hasCssError()) {
const rowsErrors = { noValue: false, isNotUnique: false };
this.checkErrorsAllRows(true, rowsErrors);
this.checkErrorsAllRows(fireCallback, rowsErrors);
if(rowsErrors.noValue) {
errors.push(new RequiredInAllRowsError(null, this));
}
Expand Down
7 changes: 2 additions & 5 deletions packages/survey-core/src/question_matrixdynamic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -735,11 +735,8 @@ export class QuestionMatrixDynamicModel extends QuestionMatrixDropdownModelBase
public get hasRowText(): boolean {
return false;
}
protected onCheckForErrors(
errors: Array<SurveyError>,
isOnValueChanged: boolean
) {
super.onCheckForErrors(errors, isOnValueChanged);
protected onCheckForErrors(errors: Array<SurveyError>, isOnValueChanged: boolean, fireCallback: boolean): void {
super.onCheckForErrors(errors, isOnValueChanged, fireCallback);
if (!isOnValueChanged && this.hasErrorInMinRows()) {
errors.push(new MinRowCountError(this.minRowCount, this));
}
Expand Down
4 changes: 2 additions & 2 deletions packages/survey-core/src/question_text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,8 @@ export class QuestionTextModel extends QuestionTextBase {
return super.valueFromDataCore(val);
}
private dateValidationMessage: string;
protected onCheckForErrors(errors: Array<SurveyError>, isOnValueChanged: boolean): void {
super.onCheckForErrors(errors, isOnValueChanged);
protected onCheckForErrors(errors: Array<SurveyError>, isOnValueChanged: boolean, fireCallback: boolean): void {
super.onCheckForErrors(errors, isOnValueChanged, fireCallback);
if (isOnValueChanged) return;
if (this.isValueLessMin) {
const minError = new CustomError(
Expand Down
23 changes: 23 additions & 0 deletions packages/survey-core/tests/question_matrix_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,29 @@ QUnit.test("matrix isAllRowRequired & getItemClass", function (assert) {
assert.equal(question.getItemClass(row, column1).indexOf(itemError) > -1, false, "itemError doesn't exist in column 1, #3");
assert.equal(question.getItemClass(row, column2).indexOf(itemError) > -1, false, "itemError doesn't exist in column 2, #3");
});
QUnit.test("matrix isAllRowRequired & getItemClass", function (assert) {
const survey = new SurveyModel({
elements: [
{
type: "matrix",
name: "q1",
columns: ["col1", "col2"],
rows: ["row1", "row2"],
isAllRowRequired: true
},
],
triggers: [{ type: "complete", expression: "{q2} = 1" }]
});
const itemError = "required_row_error";
survey.css = { matrix: { row: "row", rowError: "row_error", itemOnError: itemError } };
const question = <QuestionMatrixModel>survey.getQuestionByName("q1");
const column1 = question.columns[0];
const column2 = question.columns[1];
question.visibleRows[0].cellClick(column1);
let row = question.visibleRows[1];
assert.equal(question.getItemClass(row, column1).indexOf(itemError) > -1, false, "itemError doesn't exist in column 1, #1");
assert.equal(question.getItemClass(row, column2).indexOf(itemError) > -1, false, "itemError doesn't exist in column 2, #1");
});
QUnit.test("hideIfRowsEmpty & question visibleIf, bug#8459", function (assert) {
const survey = new SurveyModel({
elements: [{ type: "matrix", name: "q1", visibleIf: "{a}=1", hideIfRowsEmpty: true, rows: [{ value: "row1", visibleIf: "{b}=2" }] }],
Expand Down

0 comments on commit fe2e114

Please sign in to comment.