Skip to content

Commit

Permalink
Do not expand panel on checking errors if there is no errors inside it
Browse files Browse the repository at this point in the history
…fix #8341
  • Loading branch information
andrewtelnov committed May 31, 2024
1 parent 799a25b commit 96ea02f
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 28 deletions.
40 changes: 24 additions & 16 deletions src/panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -854,15 +854,12 @@ export class PanelModelBase extends SurveyElement<Question>
? rec
: {
fireCallback: fireCallback,
focuseOnFirstError: focusOnFirstError,
focusOnFirstError: focusOnFirstError,
firstErrorQuestion: <any>null,
result: false,
};
if(rec.result !== true) rec.result = false;
this.hasErrorsCore(rec);
if (rec.focuseOnFirstError && rec.firstErrorQuestion) {
rec.firstErrorQuestion.focus(true);
}
return !rec.result;
}
public validateContainerOnly(): void {
Expand All @@ -871,7 +868,7 @@ export class PanelModelBase extends SurveyElement<Question>
this.parent.validateContainerOnly();
}
}
private hasErrorsInPanels(rec: any) {
private hasErrorsInPanels(rec: any): void {
var errors = <Array<any>>[];
this.hasRequiredError(rec, errors);
if (this.survey) {
Expand All @@ -894,7 +891,7 @@ export class PanelModelBase extends SurveyElement<Question>
return text;
}

private hasRequiredError(rec: any, errors: Array<SurveyError>) {
private hasRequiredError(rec: any, errors: Array<SurveyError>): void {
if (!this.isRequired) return;
var visQuestions = <Array<any>>[];
this.addQuestionsToList(visQuestions, true);
Expand All @@ -904,13 +901,14 @@ export class PanelModelBase extends SurveyElement<Question>
}
rec.result = true;
errors.push(new OneAnswerRequiredError(this.requiredErrorText, this));
if (rec.focuseOnFirstError && !rec.firstErrorQuestion) {
if (rec.focusOnFirstError && !rec.firstErrorQuestion) {
rec.firstErrorQuestion = visQuestions[0];
}
}
protected hasErrorsCore(rec: any) {
var elements = this.elements;
var element = null;
protected hasErrorsCore(rec: any): void {
const elements = this.elements;
let element = null;
let firstErroredEl = null;
for (var i = 0; i < elements.length; i++) {
element = elements[i];

Expand All @@ -921,6 +919,9 @@ export class PanelModelBase extends SurveyElement<Question>
} else {
var question = <Question>element;
if (!question.validate(rec.fireCallback, rec)) {
if(!firstErroredEl) {
firstErroredEl = question;
}
if (!rec.firstErrorQuestion) {
rec.firstErrorQuestion = question;
}
Expand All @@ -930,6 +931,19 @@ export class PanelModelBase extends SurveyElement<Question>
}
this.hasErrorsInPanels(rec);
this.updateContainsErrors();
if(!firstErroredEl && this.errors.length > 0) {
firstErroredEl = this.getFirstQuestionToFocus(false, true);
if(!rec.firstErrorQuestion) {
rec.firstErrorQuestion = firstErroredEl;
}
}
if(rec.fireCallback && firstErroredEl) {
if(firstErroredEl === rec.firstErrorQuestion && rec.focusOnFirstError) {
firstErroredEl.focus(true);
} else {
firstErroredEl.expandAllParents();
}
}
}
protected getContainsErrors(): boolean {
var res = super.getContainsErrors();
Expand Down Expand Up @@ -1939,12 +1953,6 @@ export class PanelModel extends PanelModelBase implements IElement {
this.survey.panelVisibilityChanged(this, this.isVisible);
}
}
protected hasErrorsCore(rec: any) {
super.hasErrorsCore(rec);
if (this.isCollapsed && rec.result && rec.fireCallback) {
this.expand();
}
}
protected getRenderedTitle(str: string): string {
if (!str) {
if (this.isCollapsed || this.isExpanded) return this.name;
Expand Down
11 changes: 7 additions & 4 deletions src/question.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ export class Question extends SurveyElement<Question>
}
private focuscore(onError: boolean = false, scrollIfVisible?: boolean): void {
if (!!this.survey) {
this.expandAllParents(this);
this.expandAllParents();
this.survey.scrollElementToTop(this, this, null, this.id, scrollIfVisible);
}
var id = !onError
Expand All @@ -1204,13 +1204,16 @@ export class Question extends SurveyElement<Question>
this.fireCallback(this.focusCallback);
}
}
private expandAllParents(element: IElement) {
public expandAllParents(): void {
this.expandAllParentsCore(this);
}
private expandAllParentsCore(element: IElement) {
if (!element) return;
if (element.isCollapsed) {
element.expand();
}
this.expandAllParents((<any>element).parent);
this.expandAllParents((<any>element).parentQuestion);
this.expandAllParentsCore((<any>element).parent);
this.expandAllParentsCore((<any>element).parentQuestion);
}
public focusIn(): void {
if (!this.survey || this.isDisposed || this.isContainer) return;
Expand Down
2 changes: 1 addition & 1 deletion src/question_paneldynamic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1933,7 +1933,7 @@ export class QuestionPanelDynamicModel extends Question
for (var i = 0; i < panels.length; i++) {
var pnlError = panels[i].hasErrors(
fireCallback,
!!rec && rec.focuseOnFirstError,
!!rec && rec.focusOnFirstError,
rec
);
pnlError = this.isValueDuplicated(panels[i], keyValues, rec, fireCallback) || pnlError;
Expand Down
2 changes: 1 addition & 1 deletion src/survey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3875,7 +3875,7 @@ export class SurveyModel extends SurveyElementCore
}
var visPages = this.visiblePages;
var res = true;
const rec = { fireCallback: fireCallback, focuseOnFirstError: focusOnFirstError, firstErrorQuestion: <any>null, result: false };
const rec = { fireCallback: fireCallback, focusOnFirstError: focusOnFirstError, firstErrorQuestion: <any>null, result: false };
for (var i = 0; i < visPages.length; i++) {
if (!visPages[i].validate(fireCallback, focusOnFirstError, rec)) {
res = false;
Expand Down
89 changes: 83 additions & 6 deletions tests/paneltests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ QUnit.test("Panel with paneldynamic error focus", function (assert) {
};
const survey = new SurveyModel(json);
const rec = {
focuseOnFirstError: true,
focusOnFirstError: true,
firstErrorQuestion: <any>null,
};
const panel = survey.getPanelByName("p1");
Expand Down Expand Up @@ -373,16 +373,16 @@ QUnit.test("Required panel error focus/not focus - T3101 - Stop focus when page
const survey = new SurveyModel(json);
const page = survey.currentPage;

const rec = {
focuseOnFirstError: true,
firstErrorQuestion: <any>null,
const rec: any = {
fireCallback: true,
focusOnFirstError: true
};
page.hasErrors(true, true, rec);
assert.equal(rec.firstErrorQuestion.name, "chk1", "scroll to first question in the dynamicpanel instead of dynamicpanel itself");
assert.equal(rec.firstErrorQuestion.inputId, focusedQuestionId, "focus the question");
assert.equal(focusedQuestionId, rec.firstErrorQuestion.inputId, "focus the question");

focusedQuestionId = "";
rec.focuseOnFirstError = false;
rec.focusOnFirstError = false;
rec.firstErrorQuestion = null;
page.hasErrors(true, false, rec);
assert.notOk(focusedQuestionId, "don't scroll to question - T3101 - Stop focus when page has error");
Expand Down Expand Up @@ -2707,4 +2707,81 @@ QUnit.test("Check insert function: insert between rows", (assert) => {
assert.deepEqual(page.rows[6].visibleElements.map(q => q.name), ["q5", "q6"]);

assert.equal(calledBuildRows, 0);
});
QUnit.test("Do not expand panels on validation that doesn't have an error Bug#8341", function (assert) {
const survey = new SurveyModel({
"elements": [
{
"type": "text",
"name": "question1",
"isRequired": true
},
{
"type": "panel",
"name": "panel1",
"elements": [
{
"type": "text",
"name": "question2"
}
],
"title": "Title",
"state": "collapsed"
},
{
"type": "panel",
"name": "panel2",
"elements": [
{
"type": "text",
"name": "question3",
"isRequired": true
}
],
"title": "Title",
"state": "collapsed"
},
{
"type": "panel",
"name": "panel3",
"elements": [
{
"type": "panel",
"name": "panel4",
"elements": [
{
"type": "text",
"name": "question4",
"isRequired": true
}
],
"title": "Title",
"state": "collapsed"
}
],
"title": "Title",
"state": "collapsed"
},
{
"type": "panel",
"name": "panel5",
"isRequired": true,
"elements": [
{
"type": "text",
"name": "question2"
}
],
"title": "Title",
"state": "collapsed"
},
]
});
survey.validate(true, true);
const panels = survey.getAllPanels();
assert.equal(panels[0].isCollapsed, true, "The panel should rename collapsed");
assert.equal(panels[1].isExpanded, true, "The panel should be expanded, it has error inside, #1");
assert.equal(panels[2].isExpanded, true, "The panel should be expanded, it has error inside, #2");
assert.equal(panels[3].isExpanded, true, "The panel should be expanded, it has error inside, #3");
assert.equal(panels[4].isExpanded, true, "The panel should be expanded, panel is required, #4");
});

0 comments on commit 96ea02f

Please sign in to comment.