Create a Multi-Page Survey

This step-by-step tutorial will help you create a survey with multiple pages.

The survey below illustrates the result:

You can find the full code in the following GitHub repository: Multi-Page Survey.

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 the visible property value. If the expression evaluates to true, the page is visible; if it evaluates to false, 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. Returns false 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. Returns false if the navigation did not happen, for instance, because the current page is the first page. Unlike with nextPage(), validation errors are ignored.

  • completeLastPage()
    Completes the survey. Fails and returns false 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.

View Custom Navigation example

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 to true:

    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 the completedHtml 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 returns false 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"
};

View full code on GitHub

Further Reading

Why we use cookies.

This site uses cookies to make your browsing experience more convenient and personal. Cookies store useful information on your computer to help us improve the efficiency and relevance of our site for you. In some cases, they are essential to making the site work properly. By accessing this site, you consent to the use of cookies.

For more information, refer to DevSoft Baltic’ privacy policy and cookie policy.