diff --git a/packages/survey-core/docs/surveyjs_definition.json b/packages/survey-core/docs/surveyjs_definition.json
index 9e60be787e..17a6823462 100644
--- a/packages/survey-core/docs/surveyjs_definition.json
+++ b/packages/survey-core/docs/surveyjs_definition.json
@@ -79,16 +79,16 @@
"type": "boolean"
},
"showNavigationButtons": {
+ "type": "boolean"
+ },
+ "navigationButtonsLocation": {
"type": [
- "string",
- "numeric",
- "boolean"
+ "string"
],
"enum": [
- "none",
"top",
"bottom",
- "both"
+ "topBottom"
]
},
"showPrevButton": {
diff --git a/packages/survey-core/src/page.ts b/packages/survey-core/src/page.ts
index 6c1f83f542..08b1b803e6 100644
--- a/packages/survey-core/src/page.ts
+++ b/packages/survey-core/src/page.ts
@@ -229,14 +229,43 @@ export class PageModel extends PanelModel implements IPage {
}
@property({ defaultValue: -1, onSet: (val: number, target: PageModel) => target.onNumChanged(val) }) num: number;
/**
- * Set this property to "hide" to make "Prev", "Next" and "Complete" buttons are invisible for this page. Set this property to "show" to make these buttons visible, even if survey showNavigationButtons property is false.
- * @see SurveyMode.showNavigationButtons
+ * Obsolete. Use the [`showNavigationButtons`](https://surveyjs.io/form-library/documentation/api-reference/page-model#showNavigationButtons) property instead.
+ * @deprecated
*/
public get navigationButtonsVisibility(): string {
- return this.getPropertyValue("navigationButtonsVisibility");
+ const result = this.showNavigationButtons;
+ if (result === undefined || result === null) {
+ return "inherit";
+ }
+ return result ? "show" : "hide";
}
public set navigationButtonsVisibility(val: string) {
- this.setPropertyValue("navigationButtonsVisibility", val.toLowerCase());
+ if (typeof val == "string") {
+ val = val.toLowerCase();
+ }
+ this.showNavigationButtons = val;
+ }
+ /**
+ * Gets or sets the visibility of the Start, Next, Previous, and Complete navigation buttons on this page. Overrides the [`showNavigationButtons`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#showNavigationButtons) property specified on the survey-level.
+ *
+ * Default value: `undefined` (the visibility depends on the survey-level setting)
+ */
+ public get showNavigationButtons(): boolean | string {
+ return this.getPropertyValue("showNavigationButtons", undefined);
+ }
+ public set showNavigationButtons(val: boolean | string) {
+ this.setShowNavigationButtonsProperty(val);
+ }
+ public setShowNavigationButtonsProperty(val: boolean | string) {
+ if (val === true || val === false) {
+ this.setPropertyValue("showNavigationButtons", val);
+ } else if (val === "show") {
+ this.setPropertyValue("showNavigationButtons", true);
+ } else if (val === "hide") {
+ this.setPropertyValue("showNavigationButtons", false);
+ } else {
+ this.setPropertyValue("showNavigationButtons", undefined);
+ }
}
/**
* Returns `true` if this is the current page.
@@ -382,9 +411,12 @@ Serializer.addClass(
"page",
[
{
- name: "navigationButtonsVisibility",
- default: "inherit",
- choices: ["inherit", "show", "hide"],
+ name: "showNavigationButtons:boolean",
+ defaultFunc: () => undefined,
+ onSetValue: function (obj: any, value: any) {
+ obj && obj.setShowNavigationButtonsProperty(value);
+ },
+ alternativeName: "navigationButtonsVisibility"
},
{ name: "timeLimit:number", alternativeName: "maxTimeToFinish", default: 0, minValue: 0 },
{
diff --git a/packages/survey-core/src/settings.ts b/packages/survey-core/src/settings.ts
index 89a6836036..b76447f1c3 100644
--- a/packages/survey-core/src/settings.ts
+++ b/packages/survey-core/src/settings.ts
@@ -660,11 +660,11 @@ export var settings = {
animationEnabled: true,
/**
- * An object that specifies heading levels (`
`, ``, etc.) to use when rendering survey, page, panel, and question titles.
+ * An object that specifies HTML tags to use when rendering survey, page, panel, and question titles.
*
* Default value: `{ survey: "h3", page: "h4", panel: "h4", question: "h5" }`
*
- * If you want to modify heading levels for individual titles, handle `SurveyModel`'s [`onGetTitleTagName`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#onGetTitleTagName) event.
+ * If you want to modify HTML tags for individual titles, handle `SurveyModel`'s [`onGetTitleTagName`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#onGetTitleTagName) event.
*/
titleTags: {
survey: "h3",
diff --git a/packages/survey-core/src/survey.ts b/packages/survey-core/src/survey.ts
index 3e71f4677f..b5a5a112f4 100644
--- a/packages/survey-core/src/survey.ts
+++ b/packages/survey-core/src/survey.ts
@@ -407,11 +407,11 @@ export class SurveyModel extends SurveyElementCore
*/
public onGetQuestionTitle: EventBase = this.addEvent();
/**
- * An event that is raised when the survey calculates heading levels (``, ``, etc.) for a survey, page, panel, and question title. Handle this event to change the heading level of individual titles.
+ * An event that is raised when the survey applies HTML tags to a survey, page, panel, and question title. Handle this event to change the HTML tag of individual titles.
*
* For information on event handler parameters, refer to descriptions within the interface.
*
- * If you want to specify heading levels for all titles, use the [`titleTags`](https://surveyjs.io/form-library/documentation/api-reference/settings#titleTags) object in [global settings](https://surveyjs.io/form-library/documentation/api-reference/settings).
+ * If you want to specify HTML tags for all titles, use the [`titleTags`](https://surveyjs.io/form-library/documentation/api-reference/settings#titleTags) object in [global settings](https://surveyjs.io/form-library/documentation/api-reference/settings).
*
* [View Demo](https://surveyjs.io/form-library/examples/survey-titletagnames/ (linkStyle))
* @see onGetQuestionTitle
@@ -1569,29 +1569,56 @@ export class SurveyModel extends SurveyElementCore
this.autoFocusFirstError = val;
}
/**
- * Gets or sets the position of the Start, Next, Previous, and Complete navigation buttons and controls their visibility.
+ * Gets or sets the visibility of the Start, Next, Previous, and Complete navigation buttons.
*
* Possible values:
*
- * - `"bottom"` (default) - Displays the navigation buttons below survey content.
- * - `"top"` - Displays the navigation buttons above survey content.
- * - `"both"` - Displays the navigation buttons above and below survey content.
- * - `"none"` - Hides the navigation buttons. This setting may be useful if you [implement custom external navigation](https://surveyjs.io/form-library/examples/external-form-navigation-system/).
+ * - `true` (default) - Displays the navigation buttons.
+ * - `false` - Hides the navigation buttons. This setting may be useful if you [implement custom external navigation](https://surveyjs.io/form-library/examples/external-form-navigation-system/).
+ * @see navigationButtonsLocation
* @see autoAdvanceEnabled
* @see showPrevButton
* @see showCompleteButton
*/
- public get showNavigationButtons(): string | any {
+ public get showNavigationButtons(): boolean | any {
return this.getPropertyValue("showNavigationButtons");
}
- public set showNavigationButtons(val: string | any) {
- if (val === true || val === undefined) {
- val = "bottom";
+ public set showNavigationButtons(val: boolean | any) {
+ // if (val === true || val === undefined) {
+ // val = "bottom";
+ // }
+ // if (val === false) {
+ // val = "none";
+ // }
+ if (val === "both") {
+ val === "topBottom";
}
- if (val === false) {
- val = "none";
+ if (val === true || val === false) {
+ this.setPropertyValue("showNavigationButtons", val);
+ } else if (val === "none") {
+ this.setPropertyValue("showNavigationButtons", false);
+ } else if (["top", "bottom", "both", "topBottom"].indexOf(val) > -1) {
+ this.setPropertyValue("showNavigationButtons", true);
+ this.navigationButtonsLocation = val;
}
- this.setPropertyValue("showNavigationButtons", val);
+ }
+ /**
+ * Gets or sets the position of the Start, Next, Previous, and Complete navigation buttons. Applies only if the [`showNavigationButtons`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#showNavigationButtons) property is `true`.
+ *
+ * Possible values:
+ *
+ * - `"bottom"` (default) - Displays the navigation buttons below survey content.
+ * - `"top"` - Displays the navigation buttons above survey content.
+ * - `"topBottom"` - Displays the navigation buttons above and below survey content.
+ * @see autoAdvanceEnabled
+ * @see showPrevButton
+ * @see showCompleteButton
+ */
+ public get navigationButtonsLocation(): string | any {
+ return this.getPropertyValue("navigationButtonsLocation");
+ }
+ public set navigationButtonsLocation(val: string | any) {
+ this.setPropertyValue("navigationButtonsLocation", val);
}
/**
* Specifies whether to display the Previous button. Set this property to `false` if respondents should not move backward along the survey.
@@ -3899,13 +3926,13 @@ export class SurveyModel extends SurveyElementCore
if (this.isDesignMode) return "none";
var page = this.activePage;
if (!page) return "none";
- if (page.navigationButtonsVisibility === "show") {
- return this.showNavigationButtons === "none" ? "bottom" : this.showNavigationButtons;
- }
if (page.navigationButtonsVisibility === "hide") {
return "none";
}
- return this.showNavigationButtons;
+ if (page.navigationButtonsVisibility === "show") {
+ return !this.showNavigationButtons ? "bottom" : this.navigationButtonsLocation;
+ }
+ return !this.showNavigationButtons ? "none" : this.navigationButtonsLocation;
}
public get isNavigationButtonsShowingOnTop(): boolean {
return this.getIsNavigationButtonsShowingOn("top");
@@ -3915,7 +3942,7 @@ export class SurveyModel extends SurveyElementCore
}
private getIsNavigationButtonsShowingOn(buttonPosition: string): boolean {
var res = this.isNavigationButtonsShowing;
- return res == "both" || res == buttonPosition;
+ return res == "both" || res == "topBottom" || res == buttonPosition;
}
public get isEditMode(): boolean {
return this.mode == "edit";
@@ -8362,9 +8389,13 @@ Serializer.addClass("survey", [
"cookieName",
{ name: "partialSendEnabled:boolean", alternativeName: "sendResultOnPageNext" },
{
- name: "showNavigationButtons",
+ name: "showNavigationButtons:boolean",
+ default: true,
+ },
+ {
+ name: "navigationButtonsLocation",
default: "bottom",
- choices: ["none", "top", "bottom", "both"],
+ choices: ["top", "bottom", "topBottom"],
},
{
name: "showPrevButton:boolean",
diff --git a/packages/survey-core/tests/jsonSchemaTests.ts b/packages/survey-core/tests/jsonSchemaTests.ts
index 2f03ceee57..2e38b2d6d7 100644
--- a/packages/survey-core/tests/jsonSchemaTests.ts
+++ b/packages/survey-core/tests/jsonSchemaTests.ts
@@ -31,13 +31,23 @@ QUnit.test("generate survey schema", function (assert) {
);
assert.equal(
schema.properties.showNavigationButtons.type,
- "string",
- "showNavigationButtons is showNavigationButtons"
+ "boolean",
+ "showNavigationButtons is boolean"
);
assert.deepEqual(
schema.properties.showNavigationButtons.enum,
- ["none", "top", "bottom", "both"],
- "showNavigationButtons has enum"
+ undefined,
+ "showNavigationButtons doen't have enum"
+ );
+ assert.equal(
+ schema.properties.navigationButtonsLocation.type,
+ "string",
+ "navigationButtonsLocation is navigationButtonsLocation"
+ );
+ assert.deepEqual(
+ schema.properties.navigationButtonsLocation.enum,
+ ["top", "bottom", "topBottom"],
+ "navigationButtonsLocation has enum"
);
assert.deepEqual(
schema.properties.completedHtmlOnCondition.type,
diff --git a/packages/survey-core/tests/lowercasetests.ts b/packages/survey-core/tests/lowercasetests.ts
index 627f009846..4281e25fa0 100644
--- a/packages/survey-core/tests/lowercasetests.ts
+++ b/packages/survey-core/tests/lowercasetests.ts
@@ -30,8 +30,14 @@ QUnit.test("navigationButtonsVisibility value is always lower-case", function (
assert
) {
var question = new PageModel("base");
+ assert.strictEqual(question.navigationButtonsVisibility, "inherit");
+ assert.strictEqual(question.showNavigationButtons, undefined);
question.navigationButtonsVisibility = "HIDE";
assert.strictEqual(question.navigationButtonsVisibility, "hide");
+ assert.strictEqual(question.showNavigationButtons, false);
+ question.navigationButtonsVisibility = "Inherit";
+ assert.strictEqual(question.navigationButtonsVisibility, "inherit");
+ assert.strictEqual(question.showNavigationButtons, undefined);
});
QUnit.test(
diff --git a/packages/survey-core/tests/surveytests.ts b/packages/survey-core/tests/surveytests.ts
index aea39a8689..77446ad409 100644
--- a/packages/survey-core/tests/surveytests.ts
+++ b/packages/survey-core/tests/surveytests.ts
@@ -16064,7 +16064,8 @@ QUnit.test("firstPageIsStartPage = true and clear&state='starting'", function (a
assert.equal(survey.state, "starting", "starting state #1");
assert.equal(survey.getPropertyValue("isStartedState"), true, "isStartedState #1");
assert.equal(startButton.isVisible, true, "startButton is visible, #1");
- assert.equal(survey.showNavigationButtons, "bottom", "Show navigation on bottom");
+ assert.equal(survey.showNavigationButtons, true, "Show navigation on bottom - true");
+ assert.equal(survey.navigationButtonsLocation, "bottom", "Show navigation on bottom");
survey.start();
assert.equal(survey.state, "running", "run survey");
assert.equal(survey.getPropertyValue("isStartedState"), false, "isStartedState #2");
@@ -17604,7 +17605,8 @@ QUnit.test("getContainerContent - navigation", function (assert) {
let survey = new SurveyModel(json);
const getContainerContent = getContainerContentFunction(survey);
- assert.equal(survey.showNavigationButtons, "bottom");
+ assert.equal(survey.showNavigationButtons, true);
+ assert.equal(survey.navigationButtonsLocation, "bottom");
assert.equal(survey.progressBarType, "pages");
assert.equal(survey.showProgressBar, "off");
@@ -17727,7 +17729,7 @@ QUnit.test("getContainerContent - progress (legacyProgressBarView)", function (a
let survey = new SurveyModel(json);
const getContainerContent = getContainerContentFunction(survey);
- assert.equal(survey.showNavigationButtons, "none");
+ assert.equal(survey.showNavigationButtons, false);
assert.equal(survey.progressBarType, "pages");
assert.equal(survey.showProgressBar, "off");
@@ -17883,7 +17885,7 @@ QUnit.test("getContainerContent - progress", function (assert) {
let survey = new SurveyModel(json);
const getContainerContent = getContainerContentFunction(survey);
- assert.equal(survey.showNavigationButtons, "none");
+ assert.equal(survey.showNavigationButtons, false);
assert.equal(survey.progressBarType, "pages");
assert.equal(survey.showProgressBar, "off");
@@ -18573,7 +18575,8 @@ QUnit.test("getContainerContent - navigation with page.navigationButtonsVisibili
return result;
}
- assert.equal(survey.showNavigationButtons, "bottom");
+ assert.equal(survey.showNavigationButtons, true);
+ assert.equal(survey.navigationButtonsLocation, "bottom");
assert.deepEqual(getContainerContent("header"), [], "nav none header");
assert.deepEqual(getContainerContent("footer"), [], "nav none footer");
@@ -19771,7 +19774,7 @@ QUnit.test("getContainerContent - progress + advanced header (legacyProgressBarV
survey.headerView = "advanced";
const getContainerContent = getContainerContentFunction(survey);
- assert.equal(survey.showNavigationButtons, "none");
+ assert.equal(survey.showNavigationButtons, false);
assert.equal(survey.progressBarType, "pages");
assert.equal(survey.showProgressBar, "off");
@@ -19889,7 +19892,7 @@ QUnit.test("getContainerContent - progress + advanced header", function (assert)
survey.headerView = "advanced";
const getContainerContent = getContainerContentFunction(survey);
- assert.equal(survey.showNavigationButtons, "none");
+ assert.equal(survey.showNavigationButtons, false);
assert.equal(survey.progressBarType, "pages");
assert.equal(survey.showProgressBar, "off");