Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[QuestionPerPage] Questions inside a panel are no longer shown on the… #9590

Merged
merged 1 commit into from
Mar 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/survey-core/src/base-interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export interface ISurvey extends ITextProcessor, ISurveyErrorOwner {
isDisplayMode: boolean;
isDesignMode: boolean;
areInvisibleElementsShowing: boolean;
currentSingleQuestion: IQuestion;
currentSingleElement: IElement;
areEmptyElementsHidden: boolean;
isLoadingFromJson: boolean;
isUpdateValueTextOnTyping: boolean;
Expand Down Expand Up @@ -278,6 +278,7 @@ export interface ISurveyElement extends IShortcutText {
isReadOnly: boolean;
isPage: boolean;
isPanel: boolean;
isQuestion: boolean;
containsErrors: boolean;
parent: IPanel;
skeletonComponentName: string;
Expand Down
6 changes: 3 additions & 3 deletions packages/survey-core/src/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export class PageModel extends PanelModel implements IPage {
}
protected getElementsForRows(): Array<IElement> {
if(!this.isStartPage) {
const q = this.survey?.currentSingleQuestion;
const q = this.survey?.currentSingleElement;
if(!!q) {
if((<any>q).page === this) return [q];
return [];
Expand Down Expand Up @@ -292,9 +292,9 @@ export class PageModel extends PanelModel implements IPage {
}
}
if(this.randomizeElements(this.areQuestionsRandomized)) {
const singleQuestion: any = this.survey?.currentSingleQuestion;
const singleQuestion: any = this.survey?.currentSingleElement;
if(singleQuestion?.page === this) {
this.survey.currentSingleQuestion = this.getFirstVisibleQuestion();
this.survey.currentSingleElement = this.elements[0];
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/survey-core/src/survey-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ export class SurveyElement<E = any> extends SurveyElementCore implements ISurvey
}

private canHaveFrameStyles() {
if(<any>this.survey?.currentSingleQuestion === this) return true;
if(<any>this.survey?.currentSingleElement === this) return true;
return (this.parent !== undefined && (!this.hasParent || this.parent && (this.parent as PanelModel).showPanelAsPage));
}

Expand Down
96 changes: 56 additions & 40 deletions packages/survey-core/src/survey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3539,7 +3539,7 @@ export class SurveyModel extends SurveyElementCore
if (newPage != null && vPages.indexOf(newPage) < 0) return;
if (newPage == this.currentPage) return;
var oldValue = this.currentPage;
if (!this.isShowingPreview && !this.currentSingleQuestion && !this.currentPageChanging(newPage, oldValue)) return;
if (!this.isShowingPreview && !this.currentSingleElement && !this.currentPageChanging(newPage, oldValue)) return;
this.setPropertyValue("currentPage", newPage);
if (!!newPage) {
newPage.onFirstRendering();
Expand Down Expand Up @@ -3843,9 +3843,9 @@ export class SurveyModel extends SurveyElementCore
this.onFirstPageIsStartedChanged();
if (goToFirstPage) {
this.currentPage = this.firstVisiblePage;
if(this.currentSingleQuestion) {
if(this.currentSingleElement) {
const questions = this.getSingleQuestions();
this.currentSingleQuestion = questions.length > 0 ? questions[0] : undefined;
this.currentSingleElement = questions.length > 0 ? questions[0] : undefined;
}
}
if (clearData) {
Expand Down Expand Up @@ -3892,7 +3892,7 @@ export class SurveyModel extends SurveyElementCore
if (this.isCurrentPageRendered === true) {
this.isCurrentPageRendered = false;
}
if(!this.currentSingleQuestion) {
if(!this.currentSingleElement) {
const options = this.createPageChangeEventOptions(newValue, oldValue);
this.onCurrentPageChanged.fire(this, options);
}
Expand Down Expand Up @@ -4092,30 +4092,36 @@ export class SurveyModel extends SurveyElementCore
* @see completeLastPage
*/
public nextPage(): boolean {
if(this.currentSingleQuestion) return this.performNext();
if(this.currentSingleElement) return this.performNext();
if (this.isLastPage) return false;
return this.doCurrentPageComplete(false);
}
public performNext(): boolean {
const q = this.currentSingleQuestion;
const q: any = this.currentSingleElement;
if(!q) return this.nextPage();
if(this.validationEnabled && !q.validate(true)) return false;
const questions = this.getSingleQuestions();
const index = questions.indexOf(q);
if(index < 0 || index === questions.length - 1) return false;
const key: any = {};
key[q.name] = q.value;
this.checkTriggers(key, false, false, true, q.name);
this.currentSingleQuestion = questions[index + 1];
let keys: any = {};
if(q.isQuestion) {
keys[q.name] = q.value;
} else {
if(q.isPanel) {
keys = q.getValue();
}
}
this.checkTriggers(keys, false, false, true, q.name);
this.currentSingleElement = questions[index + 1];
return true;
}
public performPrevious(): boolean {
const q = this.currentSingleQuestion;
const q = this.currentSingleElement;
if(!q) return this.prevPage();
const questions = this.getSingleQuestions();
const index = questions.indexOf(q);
if(index === 0) return false;
this.currentSingleQuestion = questions[index - 1];
this.currentSingleElement = questions[index - 1];
return true;
}
private hasErrorsOnNavigate(doComplete: boolean): boolean {
Expand Down Expand Up @@ -4384,8 +4390,8 @@ export class SurveyModel extends SurveyElementCore
}
if (!page) return true;
let res: boolean = false;
if(this.currentSingleQuestion) {
res = !this.currentSingleQuestion.validate(true);
if(this.currentSingleElement) {
res = !(<any>this.currentSingleElement).validate(true);
} else {
res = !page.validate(true, isFocuseOnFirstError);
}
Expand Down Expand Up @@ -4421,7 +4427,7 @@ export class SurveyModel extends SurveyElementCore
* @see nextPage
*/
public prevPage(): boolean {
if(this.currentSingleQuestion) return this.performPrevious();
if(this.currentSingleElement) return this.performPrevious();
if (this.isFirstPage || this.state === "starting") return false;
this.resetNavigationButton();

Expand Down Expand Up @@ -4510,10 +4516,10 @@ export class SurveyModel extends SurveyElementCore
if (!this.isShowingPreview) return;
this.gotoPageFromPreview = currentPage;
this.isShowingPreview = false;
const q = this.currentSingleQuestion;
if(!!q?.page) {
(<PageModel>q.page).updateRows();
this.currentPage = q.page;
const page = <PageModel>(<any>this.currentSingleElement)?.page;
if(!!page) {
page.updateRows();
this.currentPage = page;
}
}
private gotoPageFromPreview: PageModel;
Expand Down Expand Up @@ -4680,7 +4686,7 @@ export class SurveyModel extends SurveyElementCore
rootPage.setSurveyImpl(this);
this.pageContainerValue = rootPage;
this.currentPage = rootPage;
if(!!this.currentSingleQuestionValue) {
if(!!this.currentSingleElementValue) {
this.visiblePages.forEach(page => page.updateRows());
}
}
Expand All @@ -4707,37 +4713,40 @@ export class SurveyModel extends SurveyElementCore
});
this.updateButtonsVisibility();
}
private currentSingleQuestionValue: Question;
private getSingleQuestions(): Array<Question> {
const res = new Array<Question>();
private currentSingleElementValue: IElement;
private getSingleQuestions(): Array<IElement> {
const res = new Array<IElement>();
const pages = this.pages;
for (var i: number = 0; i < pages.length; i++) {
const p = pages[i];
if(!p.isStartPage && p.isVisible) {
const qs: Array<any> = [];
p.addQuestionsToList(qs, true);
//p.addQuestionsToList(qs, true);
p.elements.forEach(el => qs.push(el));
qs.forEach(q => { if(q.isVisible) res.push(q); });
}
}
return res;
}
public get currentSingleQuestion(): Question {
return !this.isShowingPreview ? this.currentSingleQuestionValue : undefined;
public get currentSingleElement(): IElement {
return !this.isShowingPreview ? this.currentSingleElementValue : undefined;
}
public set currentSingleQuestion(val: Question) {
const oldVal = this.currentSingleQuestion;
public set currentSingleElement(val: IElement) {
const oldVal = this.currentSingleElement;
if(val !== oldVal && !this.isCompleted) {
const options: any = !!val && !!oldVal ? this.createPageChangeEventOptions(<PageModel>val.page, <PageModel>oldVal.page, val, oldVal) : undefined;
const valQuestion = val?.isQuestion ? <Question>val : undefined;
const oldValQuestion = oldVal?.isQuestion ? <Question>oldVal : undefined;
const page = <PageModel>(<any>val)?.page;
const options: any = !!page && !!oldVal ? this.createPageChangeEventOptions(page, <PageModel>(<any>oldVal).page, valQuestion, oldValQuestion) : undefined;
if(!!options && !this.currentPageChangingFromOptions(options)) return;
this.currentSingleQuestionValue = val;
this.currentSingleElementValue = val;
if(!!val) {
const page = <PageModel>val.page;
page.updateRows();
if(page !== this.currentPage) {
this.currentPage = page;
} else {
if(this.autoFocusFirstQuestion) {
val.focus();
if(!!valQuestion && this.autoFocusFirstQuestion) {
valQuestion.focus();
}
}
this.updateButtonsVisibility();
Expand All @@ -4749,10 +4758,17 @@ export class SurveyModel extends SurveyElementCore
}
}
}
public get currentSingleQuestion(): Question {
const res = this.currentSingleElement;
return !!res && res.isQuestion ? <Question>res : undefined;
}
public set currentSingleQuestion(val: IElement) {
this.currentSingleElement = val;
}
private changeCurrentPageFromPreview: boolean;
protected onQuestionsOnPageModeChanged(oldValue: string): void {
if (this.isShowingPreview || this.isDesignMode) return;
this.currentSingleQuestion = undefined;
this.currentSingleElement = undefined;
if(oldValue === "singlePage") {
this.updatePagesContainer();
}
Expand All @@ -4762,7 +4778,7 @@ export class SurveyModel extends SurveyElementCore
if(this.isSingleVisibleQuestion) {
const questions = this.getSingleQuestions();
if(questions.length > 0) {
this.currentSingleQuestion = questions[0];
this.currentSingleElement = questions[0];
}
}
}
Expand Down Expand Up @@ -4818,7 +4834,7 @@ export class SurveyModel extends SurveyElementCore
this.setPropertyValue("isLastPage", !!curPage && curPage === this.lastVisiblePage);
let fVal: boolean | undefined = undefined;
let lVal: boolean | undefined = undefined;
const q = this.currentSingleQuestion;
const q = this.currentSingleElement;
if(!!q) {
const questions = this.getSingleQuestions();
const index = questions.indexOf(q);
Expand Down Expand Up @@ -6979,10 +6995,10 @@ export class SurveyModel extends SurveyElementCore
const question = <Question>this.getQuestionByValueName(name);
if (!question || (!!question &&(!question.visible || !question.supportAutoAdvance()))) return;
if (!question.validate(false) && !question.supportGoNextPageError()) return;
if(!!this.currentSingleQuestion) {
const curQuestion = this.currentSingleQuestion;
if(!!this.currentSingleElement) {
const curQuestion = this.currentSingleElement;
const goNextQuestion = () => {
if (curQuestion !== this.currentSingleQuestion) return;
if (curQuestion !== this.currentSingleElement) return;
if(!this.isLastElement) {
this.performNext();
} else {
Expand Down Expand Up @@ -7967,7 +7983,7 @@ export class SurveyModel extends SurveyElementCore
if (isNeedWaitForPageRendered) {
this.currentPage = <PageModel>question.page;
if(this.isSingleVisibleQuestion && !this.isDesignMode) {
this.currentSingleQuestion = question;
this.currentSingleElement = question;
}
}
if (!isNeedWaitForPageRendered) {
Expand Down
34 changes: 27 additions & 7 deletions packages/survey-core/tests/surveytests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21191,11 +21191,10 @@ QUnit.test("questionsOnPageMode: `questionPerPage` & custom complete trigger , #
});
QUnit.test("questionsOnPageMode & question.isVisible", function (assert) {
const json = {
elements: [{ type: "panel", elements: [
elements: [
{ type: "radiogroup", "name": "q1", choices: [1, 2, 3] },
{ type: "radiogroup", "name": "q2", choices: [1, 3, 5], hideIfChoicesEmpty: true, choicesVisibleIf: "{q1} contains {item}" },
]
}],
],
questionsOnPageMode: "questionPerPage",
};
const survey = new SurveyModel(json);
Expand Down Expand Up @@ -21236,15 +21235,36 @@ QUnit.test("Do not use questionsOnPageMode in design-mode, Bug#9274", function (
assert.equal(survey.questionsOnPageMode, "questionPerPage", "the property set correctly");
assert.equal(survey.currentSingleQuestion?.name, undefined, "It is the design mode");
});
QUnit.test("questionsOnPageMode - panel should be displayed as a question", function (assert) {
const json = {
"elements": [
{ type: "panel", name: "panel1", elements: [{ "type": "text", "name": "q1" }, { "type": "text", "name": "q2" }] },
{ "type": "text", "name": "q3" },
{ type: "panel", name: "panel2", elements: [{ "type": "text", "name": "q4" }, { "type": "text", "name": "q5" }] }
],
"questionsOnPageMode": "questionPerPage",
};
const survey = new SurveyModel(json);
assert.equal(survey.currentSingleElement.name, "panel1", "currentSingleQuestion #1");
survey.performNext();
assert.equal(survey.currentSingleElement.name, "q3", "currentSingleQuestion #2");
survey.performNext();
assert.equal(survey.currentSingleElement.name, "panel2", "currentSingleQuestion #3");
survey.performPrevious();
assert.equal(survey.currentSingleElement.name, "q3", "currentSingleQuestion #4");
survey.performPrevious();
assert.equal(survey.currentSingleElement.name, "panel1", "currentSingleQuestion #5");
});
QUnit.test("question.canHaveFrameStyles should return true for questionsOnPageMode", function (assert) {
const json = {
"elements": [{ type: "panel", elements: [{ "type": "text", "name": "q1" }] }],
"elements": [{ type: "panel", name: "panel1", elements: [{ "type": "text", "name": "q1" }] }],
"questionsOnPageMode": "questionPerPage",
};
const survey = new SurveyModel(json);
const question = survey.currentSingleQuestion;
assert.equal(question.name, "q1", "currentSingleQuestion");
assert.equal(question["canHaveFrameStyles"](), true, "canHaveFrameStyles");
const question = survey.getQuestionByName("q1");
assert.equal(survey.currentSingleElement.name, "panel1", "currentSingleQuestion");
assert.equal(survey.currentSingleElement["canHaveFrameStyles"](), true, "canHaveFrameStyles - panel");
assert.equal(question["canHaveFrameStyles"](), false, "canHaveFrameStyles - question");
});
QUnit.test("question.canHaveFrameStyles should return false for questionsOnPageMode for question in dynamic panel, Bug#9572", function (assert) {
const json = {
Expand Down