Skip to content

Commit 79e0d89

Browse files
Introduce questionStartIndex on page level to allow reset the questio… (#10524)
* Introduce questionStartIndex on page level to allow reset the question index from a particular page fix #10523 * Update doccomment * Make questionStartIndex visible in the page object --------- Co-authored-by: RomanTsukanov <[email protected]>
1 parent 09fb38a commit 79e0d89

File tree

7 files changed

+109
-26
lines changed

7 files changed

+109
-26
lines changed

packages/survey-core/src/base-interfaces.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ export interface ISurvey extends ITextProcessor, ISurveyErrorOwner {
155155
actions: Array<IAction>,
156156
question?: QuestionPanelDynamicModel
157157
): Array<IAction>;
158-
questionStartIndex: string;
158+
getQuestionStartIndex(pageVisibleIndex: number): string;
159159
showQuestionNumbers: string | boolean;
160160
questionTitleLocation: string;
161161
questionDescriptionLocation: string;

packages/survey-core/src/page.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,11 @@ export class PageModel extends PanelModel implements IPage {
169169
if (this.isQuestionIndexRecursive()) return 0;
170170
return index;
171171
}
172+
protected getPageVisibleIndex(): number { return this.visibleIndex; }
172173
getQuestionStartIndex(): string {
173174
const res = this.getStartIndex();
174175
if (this.isQuestionIndexRecursive()) {
175-
return this.getQuestionStartIndexVsVisibleIndex(res, this.visibleIndex);
176+
return this.getQuestionStartIndexVsVisibleIndex(res, this.num - 1);
176177
}
177178
return res;
178179
}
@@ -461,7 +462,6 @@ Serializer.addClass(
461462
{ name: "page", visible: false, isSerializable: false },
462463
{ name: "showNumber", visible: false },
463464
{ name: "showQuestionNumbers", visible: false },
464-
{ name: "questionStartIndex", visible: false },
465465
{ name: "allowAdaptiveActions", visible: false },
466466
{ name: "requiredErrorText:text", serializationProperty: "locRequiredErrorText", visible: false },
467467
],

packages/survey-core/src/panel.ts

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,25 @@ export class PanelModelBase extends SurveyElement<Question>
566566
public set questionsOrder(val: string) {
567567
this.questionOrder = val;
568568
}
569+
/**
570+
* Specifies a number or letter used to start numbering of elements inside this page/panel.
571+
*
572+
* You can include desired prefixes and postfixes alongside the number or letter:
573+
*
574+
* ```js
575+
* "questionStartIndex": "a.", // a., b., c., ...
576+
* "questionStartIndex": "#3", // #3, #4, #5, ...
577+
* "questionStartIndex": "(B)." // (B)., (C)., (D)., ...
578+
* ```
579+
* Default value: `"1."` (inherited from the `questionStartIndex` property specified for the parent panel, page, or survey)
580+
* @see showQuestionNumbers
581+
*/
582+
public get questionStartIndex(): string {
583+
return this.getPropertyValue("questionStartIndex", "");
584+
}
585+
public set questionStartIndex(val: string) {
586+
this.setPropertyValue("questionStartIndex", val);
587+
}
569588
public addNoFromChild(no: string): string { return no; }
570589
private canRandomize(isRandom: boolean): boolean {
571590
return isRandom && (this.questionOrder !== "initial") || this.questionOrder === "random";
@@ -2243,6 +2262,7 @@ export class PanelModel extends PanelModelBase implements IElement {
22432262
* - `"off"` - Hides question numbers within this page/panel.
22442263
* @see [SurveyModel.showQuestionNumbers](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#showQuestionNumbers)
22452264
* @see showNumber
2265+
* @see questionStartIndex
22462266
*/
22472267
public get showQuestionNumbers(): string {
22482268
return this.getPropertyValue("showQuestionNumbers");
@@ -2251,26 +2271,7 @@ export class PanelModel extends PanelModelBase implements IElement {
22512271
this.setPropertyValue("showQuestionNumbers", value);
22522272
this.notifySurveyOnVisibilityChanged();
22532273
}
2254-
/**
2255-
* Specifies a number or letter used to start numbering of elements inside the panel.
2256-
*
2257-
* You can include desired prefixes and postfixes alongside the number or letter:
2258-
*
2259-
* ```js
2260-
* "questionStartIndex": "a.", // a., b., c., ...
2261-
* "questionStartIndex": "#3", // #3, #4, #5, ...
2262-
* "questionStartIndex": "(B)." // (B)., (C)., (D)., ...
2263-
* ```
2264-
* Default value: `"1."` (inherited from `SurveyModel`'s `questionStartIndex` property)
2265-
* @see SurveyModel.questionStartIndex
2266-
* @see showQuestionNumbers
2267-
*/
2268-
public get questionStartIndex(): string {
2269-
return this.getPropertyValue("questionStartIndex", "");
2270-
}
2271-
public set questionStartIndex(val: string) {
2272-
this.setPropertyValue("questionStartIndex", val);
2273-
}
2274+
protected getPageVisibleIndex(): number { return (<any>this.page)?.visibleIndex || -1; }
22742275
getQuestionStartIndex(): string {
22752276
const res = this.questionStartIndex;
22762277
if (!!res && this.isQuestionIndexOnPanel && this.isComplexIndex(res))

packages/survey-core/src/question.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,7 @@ export class Question extends SurveyElement<Question>
571571
public getPanels(): Array<IPanel> {
572572
return null;
573573
}
574+
protected getPageVisibleIndex(): number { return (<any>this.page)?.visibleIndex || -1; }
574575
public delete(doDispose: boolean = true): void {
575576
this.removeFromParent();
576577
if (doDispose) {

packages/survey-core/src/survey-element.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -847,9 +847,10 @@ export class SurveyElement<E = any> extends SurveyElementCore implements ISurvey
847847
public setVisibleIndex(index: number): number {
848848
return 0;
849849
}
850+
protected getPageVisibleIndex(): number { return -1; }
850851
protected getStartIndex(): string {
851852
if (!!this.parent) return this.parent.getQuestionStartIndex();
852-
if (!!this.survey) return this.survey.questionStartIndex;
853+
if (!!this.survey) return this.survey.getQuestionStartIndex(this.getPageVisibleIndex());
853854
return "";
854855
}
855856
public delete(doDispose: boolean): void { }

packages/survey-core/src/survey.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1828,6 +1828,15 @@ export class SurveyModel extends SurveyElementCore
18281828
public set questionStartIndex(val: string) {
18291829
this.setPropertyValue("questionStartIndex", val);
18301830
}
1831+
getQuestionStartIndex(pageVisibleIndex: number): string {
1832+
if (pageVisibleIndex >= 0 && pageVisibleIndex < this.visiblePages.length) {
1833+
for (let i = pageVisibleIndex; i >= 0; i--) {
1834+
const page = this.visiblePages[i];
1835+
if (!!page.questionStartIndex) return page.questionStartIndex;
1836+
}
1837+
}
1838+
return this.questionStartIndex;
1839+
}
18311840
/**
18321841
* Specifies whether to store the "Other" option response in a separate property.
18331842
*
@@ -6675,12 +6684,18 @@ export class SurveyModel extends SurveyElementCore
66756684
}
66766685
private updatePageVisibleIndexes(): void {
66776686
this.updateButtonsVisibility();
6678-
var index = 0;
6687+
let index = 0;
6688+
let numIndex = 1;
6689+
this.pages.forEach(page => {
6690+
});
66796691
for (var i = 0; i < this.pages.length; i++) {
66806692
const page = this.pages[i];
66816693
const isPageVisible = page.isVisible && (i > 0 || !page.isStartPage);
6694+
if (!!page.questionStartIndex) {
6695+
numIndex = 1;
6696+
}
66826697
page.visibleIndex = isPageVisible ? index++ : -1;
6683-
page.num = isPageVisible ? page.visibleIndex + 1 : -1;
6698+
page.num = isPageVisible ? numIndex++ : -1;
66846699
}
66856700
}
66866701
public fromJSON(json: any, options?: ILoadFromJSONOptions): void {

packages/survey-core/tests/paneltests.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3739,3 +3739,68 @@ QUnit.test("Panel.validate vs callback function as a parameter #10307", function
37393739

37403740
FunctionFactory.Instance.unregister("asyncFunc");
37413741
});
3742+
QUnit.test("page questionStartIndex, Issue#10523", function (assert) {
3743+
const survey = new SurveyModel({
3744+
pages: [{
3745+
elements: [
3746+
{
3747+
type: "text",
3748+
name: "q1"
3749+
}] },
3750+
{
3751+
elements: [
3752+
{
3753+
type: "text",
3754+
name: "q2"
3755+
}] },
3756+
{
3757+
questionStartIndex: "A.1",
3758+
elements: [
3759+
{
3760+
type: "panel", name: "p1", title: "Panel",
3761+
elements: [
3762+
{ type: "text", name: "q3" },
3763+
{ type: "text", name: "q4" }
3764+
]
3765+
},
3766+
] },
3767+
{ elements: [
3768+
{ type: "text", name: "q5" },
3769+
{
3770+
type: "panel", name: "p2", title: "Panel",
3771+
elements: [
3772+
{ type: "text", name: "q6" },
3773+
{ type: "text", name: "q7" }
3774+
]
3775+
}]
3776+
}],
3777+
showQuestionNumbers: "recursive",
3778+
questionStartIndex: "1.1"
3779+
});
3780+
assert.equal(survey.pages[1].visibleIndex, 1, "page2.visibleIndex, #1");
3781+
assert.equal(survey.pages[1].num, 2, "page2.num, #2");
3782+
assert.equal(survey.pages[2].questionStartIndex, "A.1", "questionStartIndex, #1");
3783+
assert.equal(survey.pages[2].visibleIndex, 2, "page2.visibleIndex, #1");
3784+
assert.equal(survey.pages[2].num, 1, "page2.num, #2");
3785+
assert.equal(survey.pages[3].visibleIndex, 3, "page3.visibleIndex, #1");
3786+
assert.equal(survey.pages[3].num, 2, "page3.num, #1");
3787+
const q1 = survey.getQuestionByName("q1");
3788+
const q2 = survey.getQuestionByName("q2");
3789+
const q3 = survey.getQuestionByName("q3");
3790+
const q4 = survey.getQuestionByName("q4");
3791+
const q5 = survey.getQuestionByName("q5");
3792+
const q6 = survey.getQuestionByName("q6");
3793+
const q7 = survey.getQuestionByName("q7");
3794+
const p1 = survey.getPanelByName("p1");
3795+
const p2 = survey.getPanelByName("p2");
3796+
3797+
assert.equal(q1.no, "1.1", "q1, #1");
3798+
assert.equal(q2.no, "2.1", "q2, #1");
3799+
assert.equal(p1.no, "A.1", "panel1, #1");
3800+
assert.equal(q3.no, "A.1.1", "q3, #1");
3801+
assert.equal(q4.no, "A.1.2", "q4, #1");
3802+
assert.equal(q5.no, "B.1", "q5, #1");
3803+
assert.equal(p2.no, "B.2", "panel2, #1");
3804+
assert.equal(q6.no, "B.2.1", "q6, #1");
3805+
assert.equal(q7.no, "B.2.2", "q7, #1");
3806+
});

0 commit comments

Comments
 (0)