Create a Multi-Page Survey
This step-by-step tutorial will help you create a survey with multiple pages.
- Add Multiple Pages to a Survey
- Configure Page Visibility
- Configure Page Navigation
- Configure Special Pages
- Render the Survey
The survey below illustrates the result:
Add Multiple Pages to a Survey
A page is a container for other survey elements (panels and questions). Pages cannot be nested into each other. Every survey should have at least one visible page.
To configure pages, define the pages
array in the survey model. Each object in this array configures a single Page. Within the object, specify the elements
array to configure the page's questions and panels.
The following model defines a four-page survey that contains the Radiogroup, Comment, and Rating question types. The pages are shown in order. The next step is to implement logic that hides specific pages based on the "satisfaction-score"
question value.
const surveyJson = {
pages: [{
elements: [{
name: "satisfaction-score",
title: "How would you describe your experience with our product?",
type: "radiogroup",
choices: [
{ value: 5, text: "Fully satisfying" },
{ value: 4, text: "Generally satisfying" },
{ value: 3, text: "Neutral" },
{ value: 2, text: "Rather unsatisfying" },
{ value: 1, text: "Not satisfying at all" }
],
isRequired: true
}]
}, {
elements: [{
name: "what-would-make-you-more-satisfied",
title: "What can we do to make your experience more satisfying?",
type: "comment",
}, {
name: "nps-score",
title: "On a scale of zero to ten, how likely are you to recommend our product to a friend or colleague?",
type: "rating",
rateMin: 0,
rateMax: 10
}],
}, {
elements: [{
name: "how-can-we-improve",
title: "In your opinion, how could we improve our product?",
type: "comment"
}],
}, {
elements: [{
name: "disappointing-experience",
title: "Please let us know why you had such a disappointing experience with our product",
type: "comment"
}],
}]
};
Configure Page Visibility
You can use the following properties to control page visibility:
visible
A Boolean value that specifies whether the page is visible.visibleIf
A Boolean expression used to calculate thevisible
property value. If the expression evaluates totrue
, the page is visible; if it evaluates tofalse
, the page is hidden. The expression is evaluated for the first time when the survey begins, and then re-evaluated again each time any of the question values change.
The visible
and visibleIf
properties are supported by pages, but you can also set these properties for nested panels and questions. If a page is hidden or all panels and questions on it are hidden, the survey skips this page automatically.
In the following code, the visibleIf
property is set to a Boolean expression that specifies the visibility of pages and questions based on the "satisfaction-score"
question value:
const surveyJson = {
pages: [{
elements: [{
name: "satisfaction-score",
// ...
}]
}, {
elements: [{
name: "what-would-make-you-more-satisfied",
// ...
visibleIf: "{satisfaction-score} = 4"
}, {
name: "nps-score",
// ...
}],
visibleIf: "{satisfaction-score} >= 4"
}, {
elements: [{
name: "how-can-we-improve",
// ...
}],
visibleIf: "{satisfaction-score} = 3"
}, {
elements: [{
name: "disappointing-experience",
// ...
}],
visibleIf: "{satisfaction-score} =< 2"
}],
};
If you need to access an array of visible pages, use the SurveyModel's visiblePages
property. If you only need the number of visible pages, use the visiblePageCount
property. Both properties update dynamically as the respondent progresses in the survey.
View Full Survey Model
const surveyJson = {
pages: [{
elements: [{
name: "satisfaction-score",
title: "How would you describe your experience with our product?",
type: "radiogroup",
choices: [
{ value: 5, text: "Fully satisfying" },
{ value: 4, text: "Generally satisfying" },
{ value: 3, text: "Neutral" },
{ value: 2, text: "Rather unsatisfying" },
{ value: 1, text: "Not satisfying at all" }
],
isRequired: true
}]
}, {
elements: [{
name: "what-would-make-you-more-satisfied",
title: "What can we do to make your experience more satisfying?",
type: "comment",
visibleIf: "{satisfaction-score} = 4"
}, {
name: "nps-score",
title: "On a scale of zero to ten, how likely are you to recommend our product to a friend or colleague?",
type: "rating",
rateMin: 0,
rateMax: 10
}],
visibleIf: "{satisfaction-score} >= 4"
}, {
elements: [{
name: "how-can-we-improve",
title: "In your opinion, how could we improve our product?",
type: "comment"
}],
visibleIf: "{satisfaction-score} = 3"
}, {
elements: [{
name: "disappointing-experience",
title: "Please let us know why you had such a disappointing experience with our product",
type: "comment"
}],
visibleIf: "{satisfaction-score} =< 2"
}],
showQuestionNumbers: "off",
};
Configure Page Navigation
Switch Between Pages
To switch between pages, use the currentPage
property. It contains the page the respondent currently works with. You can set this property to one of the following values:
const survey = new Survey.Model(surveyJson);
// A page instance
survey.currentPage = myPage;
// A zero-based index of the desired page in the `visiblePages` array
survey.currentPage = visiblePageIndex;
// A page name
survey.currentPage = "myCurrentPage";
If you need to get the index of the current page in the visiblePages
array, use the currentPageNo
property:
const visiblePageIndex = survey.currentPageNo;
You can also use the following methods for page navigation:
start()
Begins the survey. Use this method only if you have a start page.nextPage()
Navigates the respondent to the next page. Returnsfalse
if the navigation did not happen, for instance, because of validation errors or if the current page is the last page.prevPage()
Navigates the respondent to the previous page. Returnsfalse
if the navigation did not happen, for instance, because the current page is the first page. Unlike withnextPage()
, validation errors are ignored.completeLastPage()
Completes the survey. Fails and returnsfalse
if the current page has validation errors.doComplete()
Completes the survey regardless of present validation errors.
The following code shows how to call the described methods and handle possible navigation errors:
const survey = new Survey.Model(surveyJson);
survey.start();
const navigatedForward = survey.nextPage();
if (!navigatedForward) {
alert("Navigation failed!")
}
const navigatedBack = survey.prevPage();
if (!navigatedBack) {
alert("Navigation failed!")
}
const completedSuccessfully = survey.completeLastPage();
if (!completedSuccessfully) {
alert("Check the answers for validation errors")
}
survey.doComplete();
In this tutorial, the survey uses out-of-the-box page navigation and does not demonstrate the described API members. However, the given information should help you implement custom page navigation if you find it more suitable in your scenario.
Page Navigation UI
Respondents can click the Next, Previous, and Complete buttons to navigate survey pages. To change button captions, you can specify the SurveyModel's pageNextText
, pagePrevText
, and completeText
properties.
const surveyJson = {
pageNextText: "Forward",
pagePrevText: "Back",
completeText: "Submit"
};
If you want to hide the buttons, set the showNavigationButtons
property to "none"
. In this case, you can use the API described in the Switch Between Pages article to implement custom page navigation. Alternatively, you can enable the goNextPageAutomatic
and allowCompleteSurveyAutomatic
properties to proceed to the next page or complete the survey automatically when all questions are answered.
const surveyJson = {
showNavigationButtons: "none",
goNextPageAutomatic: true,
allowCompleteSurveyAutomatic: true
};
If you only want to hide the Previous button, disable the showPrevButton
property. Note that respondents will still be able to edit their previous answers on the preview page if you add it to your survey.
const surveyJson = {
showPrevButton: false,
};
You can also indicate survey progress on a progress bar. To display and position it on the page, set the showProgressBar
property to "top"
, "bottom"
, or "both"
.
const surveyJson = {
showProgressBar: "top"
};
The example in this tutorial uses only the pageNextText
, completeText
, and showPrevButton
properties:
View Full Survey Model
const surveyJson = {
pages: [{
elements: [{
name: "satisfaction-score",
title: "How would you describe your experience with our product?",
type: "radiogroup",
choices: [
{ value: 5, text: "Fully satisfying" },
{ value: 4, text: "Generally satisfying" },
{ value: 3, text: "Neutral" },
{ value: 2, text: "Rather unsatisfying" },
{ value: 1, text: "Not satisfying at all" }
],
isRequired: true
}]
}, {
elements: [{
name: "what-would-make-you-more-satisfied",
title: "What can we do to make your experience more satisfying?",
type: "comment",
visibleIf: "{satisfaction-score} = 4"
}, {
name: "nps-score",
title: "On a scale of zero to ten, how likely are you to recommend our product to a friend or colleague?",
type: "rating",
rateMin: 0,
rateMax: 10
}],
visibleIf: "{satisfaction-score} >= 4"
}, {
elements: [{
name: "how-can-we-improve",
title: "In your opinion, how could we improve our product?",
type: "comment"
}],
visibleIf: "{satisfaction-score} = 3"
}, {
elements: [{
name: "disappointing-experience",
title: "Please let us know why you had such a disappointing experience with our product",
type: "comment"
}],
visibleIf: "{satisfaction-score} =< 2"
}],
showQuestionNumbers: "off",
pageNextText: "Forward",
completeText: "Submit",
showPrevButton: false,
};
Configure Special Pages
Start Page
A start page usually shows an introduction to your survey. It does not affect the survey progress, and users cannot return to it once they start the survey. If you want to add a start page to your survey, configure the page in the first object of the pages
array. In the code below, the start page contains HTML markup:
const surveyJson = {
pages: [{
elements: [{
type: "html",
html: "<h2>In this survey, we will ask you a couple questions about your impressions of our product.</h2>"
}]
},
// ...
// Other pages are configured here
// ...
],
};
Enable the firstPageIsStarted
property to let the survey know that the first page is a start page and add a Start button to the page markup. You can use the startSurveyText
property to change the button caption:
const surveyJson = {
firstPageIsStarted: true,
startSurveyText: "Take the Survey",
};
If you need to access the start page in code, you can use the startedPage
property:
const survey = new Survey.Model(surveyJson);
const startPage = survey.startedPage;
View Full Survey Model
const surveyJson = {
pages: [{
elements: [{
type: "html",
html: "<h2>In this survey, we will ask you a couple questions about your impressions of our product.</h2>"
}]
}, {
elements: [{
name: "satisfaction-score",
title: "How would you describe your experience with our product?",
type: "radiogroup",
choices: [
{ value: 5, text: "Fully satisfying" },
{ value: 4, text: "Generally satisfying" },
{ value: 3, text: "Neutral" },
{ value: 2, text: "Rather unsatisfying" },
{ value: 1, text: "Not satisfying at all" }
],
isRequired: true
}]
}, {
elements: [{
name: "what-would-make-you-more-satisfied",
title: "What can we do to make your experience more satisfying?",
type: "comment",
visibleIf: "{satisfaction-score} = 4"
}, {
name: "nps-score",
title: "On a scale of zero to ten, how likely are you to recommend our product to a friend or colleague?",
type: "rating",
rateMin: 0,
rateMax: 10
}],
visibleIf: "{satisfaction-score} >= 4"
}, {
elements: [{
name: "how-can-we-improve",
title: "In your opinion, how could we improve our product?",
type: "comment"
}],
visibleIf: "{satisfaction-score} = 3"
}, {
elements: [{
name: "disappointing-experience",
title: "Please let us know why you had such a disappointing experience with our product",
type: "comment"
}],
visibleIf: "{satisfaction-score} =< 2"
}],
showQuestionNumbers: "off",
pageNextText: "Forward",
completeText: "Submit",
showPrevButton: false,
firstPageIsStarted: true,
startSurveyText: "Take the Survey",
};
Complete Page
A complete page displays a "Thank you" message when the survey ends. If you want to specify a custom message, use the following properties:
completedHtml
Custom HTML content displayed on the complete page.const surveyJson = { completedHtml: "Thank you for your feedback!", };
completedHtmlOnCondition
An array that allows you to specify different complete page content based on conditions. Each object is this array should contain a Boolean expression and HTML markup that applies when this expression evaluates totrue
:const surveyJson = { completedHtmlOnCondition: [{ expression: "{some_field} > 10", html: "Custom markup to show when some_field is greater than 10" }, { expression: "{some_field} < 10", html: "Custom markup to show when some_field is less than 10" }, // ... ] };
When none of the expressions evaluate to
true
, the complete page displays the HTML markup from thecompletedHtml
property.
If your survey should not display a complete page, disable the showCompletedPage
property.
View Full Survey Model
const surveyJson = {
pages: [{
elements: [{
type: "html",
html: "<h2>In this survey, we will ask you a couple questions about your impressions of our product.</h2>"
}]
}, {
elements: [{
name: "satisfaction-score",
title: "How would you describe your experience with our product?",
type: "radiogroup",
choices: [
{ value: 5, text: "Fully satisfying" },
{ value: 4, text: "Generally satisfying" },
{ value: 3, text: "Neutral" },
{ value: 2, text: "Rather unsatisfying" },
{ value: 1, text: "Not satisfying at all" }
],
isRequired: true
}]
}, {
elements: [{
name: "what-would-make-you-more-satisfied",
title: "What can we do to make your experience more satisfying?",
type: "comment",
visibleIf: "{satisfaction-score} = 4"
}, {
name: "nps-score",
title: "On a scale of zero to ten, how likely are you to recommend our product to a friend or colleague?",
type: "rating",
rateMin: 0,
rateMax: 10
}],
visibleIf: "{satisfaction-score} >= 4"
}, {
elements: [{
name: "how-can-we-improve",
title: "In your opinion, how could we improve our product?",
type: "comment"
}],
visibleIf: "{satisfaction-score} = 3"
}, {
elements: [{
name: "disappointing-experience",
title: "Please let us know why you had such a disappointing experience with our product",
type: "comment"
}],
visibleIf: "{satisfaction-score} =< 2"
}],
showQuestionNumbers: "off",
pageNextText: "Forward",
completeText: "Submit",
showPrevButton: false,
firstPageIsStarted: true,
startSurveyText: "Take the Survey",
completedHtml: "Thank you for your feedback!",
};
Preview Page
A preview page allows respondents to preview and correct their answers before the survey is completed. The preview page displays all visible survey pages as panels. Each panel has an Edit button that sends the respondent back to the corresponding page.
To enable the preview page, specify whether it should display all visible questions or only those that have answers. Set the showPreviewBeforeComplete
property to "showAllQuestions"
or "showAnsweredQuestions"
:
const surveyJson = {
showPreviewBeforeComplete: "showAnsweredQuestions"
};
When the preview page is enabled, the last page in the survey displays a Preview button instead of a Complete button. Set the previewText
property if you want to change the Preview button caption:
const surveyJson = {
previewText: "Preview answers"
};
You can also call the following methods to control preview page visibility in code:
showPreview()
Shows the preview page. Fails and returnsfalse
if the current page has validation errors.cancelPreview()
Hides the preview page and switches the survey back to edit mode.
The following code shows how to call these methods and handle possible errors:
const survey = new Survey.Model(surveyJson);
const previewShown = survey.showPreview();
if (!previewShown) {
alert("Check the answers for validation errors")
}
survey.cancelPreview();
The example in this tutorial uses only the showPreviewBeforeComplete
property:
View Full Survey Model
const surveyJson = {
pages: [{
elements: [{
type: "html",
html: "<h2>In this survey, we will ask you a couple questions about your impressions of our product.</h2>"
}]
}, {
elements: [{
name: "satisfaction-score",
title: "How would you describe your experience with our product?",
type: "radiogroup",
choices: [
{ value: 5, text: "Fully satisfying" },
{ value: 4, text: "Generally satisfying" },
{ value: 3, text: "Neutral" },
{ value: 2, text: "Rather unsatisfying" },
{ value: 1, text: "Not satisfying at all" }
],
isRequired: true
}]
}, {
elements: [{
name: "what-would-make-you-more-satisfied",
title: "What can we do to make your experience more satisfying?",
type: "comment",
visibleIf: "{satisfaction-score} = 4"
}, {
name: "nps-score",
title: "On a scale of zero to ten, how likely are you to recommend our product to a friend or colleague?",
type: "rating",
rateMin: 0,
rateMax: 10
}],
visibleIf: "{satisfaction-score} >= 4"
}, {
elements: [{
name: "how-can-we-improve",
title: "In your opinion, how could we improve our product?",
type: "comment"
}],
visibleIf: "{satisfaction-score} = 3"
}, {
elements: [{
name: "disappointing-experience",
title: "Please let us know why you had such a disappointing experience with our product",
type: "comment"
}],
visibleIf: "{satisfaction-score} =< 2"
}],
showQuestionNumbers: "off",
pageNextText: "Forward",
completeText: "Submit",
showPrevButton: false,
firstPageIsStarted: true,
startSurveyText: "Take the Survey",
completedHtml: "Thank you for your feedback!",
showPreviewBeforeComplete: "showAnsweredQuestions"
};
Render the Survey
Refer to the following platform-specific articles for information on how to render the survey in your application:
- Render the Survey - Angular
- Render the Survey - Vue
- Render the Survey - React
- Render the Survey - HTML/CSS/JavaScript