v 1.7.10

SurveyJS Library Overview

This article describes how SurveyJS Library works, its concepts and main functionality.

We recommend that you use the SurveyJS Creator to create a survey without any coding.

For information about integrating a survey into a web page, refer to the Add Survey into your Web Page article.

Please visit our what's new page to see what we have added recently or what is coming soon.

Supported Platforms

The SurveyJS Library is a JavaScript library that available for five platforms:

  • angular2+
  • jQuery
  • knockout
  • react
  • vue

Please note: If you do not use any of this framework and do not use jQuery, then the right choice is knockout. It is a small library that helps creating UI with Model-View-View-Model pattern. You can include knockout script (~25k min+gz) just for SurveyJS and forget about this library existing in your application.

The library itself consists of two parts:

  • Survey Model

    A platform independent part. In the most case, you work with Survey Model.

  • The platform specific code

    This part deals with rendering and processing mouse and keyboard events.

    The jQuery and angular2+ versions are the wrappers around the knockout version with built-in knockout library in them. Knockout, react, and vue implementations are native.

Survey Objects

SurveyJS implements three main object types:

  • survey,
  • containers (pages and panels),
  • questions.

The survey object is the root element, that contains top level properties/options, methods, and events. It contains top-level containers – pages. Every page may contain unlimited number of panels and questions, where panel can contain another panels and questions (nested panels are supported).

Create Simple Survey Model (Using JSON or in Code)

You can create a survey model in two ways:

  • define a survey model in JSON and pass a JSON object to the Survey's constructor as a parameter
  • create a survey model in code.

In JSON

The example below demonstrates how to create a simple survey model using JSON. This survey contains a single page and a text question in it:

var json = {
  pages: [
    {
      name: "page1",
      elements: [
        { type: "text", name: "question1" }
      ]
    }
  ]
}
var survey = new Survey.Survey(json);

In the example above, the survey model contains a single page. In this case, you can remove the "pages" and "page1" definition: SurveyJS creates a page automatically. As result, the JSON may look like follows:

var json = {
    elements: [
      { type: "text", name: "question1" }
    ]
  }
var survey = new Survey.Survey(json);

In Code

You can create a survey in code:

var survey = new Survey.Survey();
var page = survey.addNewPage("page1");
page.addNewQuestion("text", "question1");

In JSON and in Code

You can combine these two approaches.

The example below demonstrates how to create a survey model in JSON and then modify the model in code.

var json = {
  pages: [
    {
      name: "customerContact", elements: [
        { type: "text", name: "name", title: "Please enter your name:" },
        { type: "text", name: "email", title: "Please enter your e-mail:" }
      ]
    }
  ]
  };
  // Create initial survey model using json
  var survey = new Survey.Survey(json);
  // Create a placeholder for an "email" question
  var emailQuestion = survey.getQuestionByName("email");
  if (emailQuestion) emailQuestion.placeHolder = "json.snow@nightwatch.org";
  // Add a new question into an existing page
  var contactPage = survey.getPageByName("customerContact");
  if (contactPage) {
    var fbPageQuestion = contactPage.addNewQuestion("text", "fbPage");
    fbPageQuestion.title = "Please enter your facebook page:"
  }
  //You may create a new page or remove/add pages, add/remove questions, panels, modify them, etc.

Load Survey From SurveyJS Service

SurveyJS allows you to load a survey model JSON from SurveyJS Service. The main benefit of this approach – you can modify the survey without modifying your web page.

To load survey model from SurveyJS Service, do the following:

  1. Register on SurveyJS web site.

  2. Create a new Survey in the SurveyJS Service.

  3. In the SurveyJS Service page, copy your Survey Id.

    get survey id

  4. Create a survey as shown in a code sample below.

    var json = {
      surveyId: '5af48e08-a0a5-44a5-83f4-1c90e8e98de1'
      };
    var survey = new Survey.Survey(json);
    

Example

Demo: Load a survey from SurveyJS Service.

Store Survey Results

After you have created your survey and integrated it into your web site, you need to save the survey results.

You may store survey results:

Use SurveyJS Service Backend

SurveyJS has the backend SurveyJS Service to store your surveys' results. This approach doesn't require to write any code and is free for now.

To store survey results on SurveyJS backend, do the following:

  1. Register on SurveyJS web site.

  2. Create a new survey. If you do not want to load the survey from SurveyJS service, then you do not need to keep the survey definition in the service.

  3. Get a Post Id for a new survey:

    survey get post id

  4. Set the Survey's surveyPostId to the PostId value:

    var survey = new Survey.Survey(json);
    survey.surveyPostId = "YourPostIdGuid";
    //Optionally, show saving progress and show an error and "Save Again" button if the results can't be stored.
    survey.surveyShowDataSaving = true;
    

Example

Save survey results in SurveyJS backend

Show Progress and Try Again Button

You can optionally show the saving progress by setting the surveyShowDataSaving property to true. When the option is enabled, the survey shows the "Saving..." message. Then, the survey shows if the operation was successful or an error occurred after the callback from SurveyJS service.

If an error occurs, the survey displays the "Save Again" button, so an end user can try to send survey results again.

You can override the default UI and message texts as shown in the code sample below.

Survey.surveyStrings.savingData = "Please wait. We are validating and saving your response.";
Survey.surveyStrings.savingDataError = "That is my own text on error.";
Survey.surveyStrings.savingDataSuccess = "That is my own text on success.";
Survey.surveyStrings.saveAgainButton = "Try to save again.";

Refer to Localization and Multilanguages support section for more information on SurveyJS strings and localization

Store Survey Results in Your Own Database

To store the survey results in your own storage, you use the onComplete event. It fires when an end user clicks the "Complete" button and a survey completion page is displayed.

The implementation of the storing survey results in the database is fully depends on your server backend and database.

The code sample below demonstrates how to send the survey results to your service, in case you have implemented the services on your web site:

survey.onComplete.add(function (sender, options) {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "YourServiceForStoringSurveyResultsAsJSON_URL");
    xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    xhr.send(JSON.stringify(sender.data));
});

Show Progress and Try Again Button

You can show the progress and error messages:

survey.onComplete.add(function (sender, options) {
    //Show message about "Saving..." the results
    options.showDataSaving();//you may pass a text parameter to show your own text
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "YourServiceForStoringSurveyResultsURL");
    xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    xhr.onload = xhr.onerror = function () {
        if (xhr.status == 200) {
            options.showDataSavingSuccess(); // you may pass a text parameter to show your own text
            // Or you may clear all messages:
            // options.showDataSavingClear();
        } else {
            //Error
            options.showDataSavingError(); // you may pass a text parameter to show your own text
        }
    };
    xhr.send(JSON.stringify(sender.data));
});

Modify Survey Results

SurveyJS sends survey results in the following format:

{questionName: questionValue, ... }

The code sample below demonstrates how to change the standard format to

{ questionName:
    {
        value: questionValue,
        title: questionTitle,
        displayValue: questionDisplayValue,
        tag: question.tag
    }
}

... where tag is a custom property added into question class.

// Adding custom numeric property to a question
// Survey.Serializer.addProperty("question", "tag:number")
function modifySurveyResults(survey) {
  var resultData = [];
  for(var key in survey.data) {
    var question = survey.getQuestionByValueName(key);
    if(!!question) {
      var item = {value: question.value};
      //If question name (question.valueName) doesn't equal to question.title
      if(key !== question.title) {
        item.title = question.title;
      }
      //If question value different from displayValue
      if(item.value != question.displayValue) {
        item.displayValue = question.displayValue
      }
      //If the custom property tag is defined set
      if(question.tag !== undefined) {
        item.tag = question.tag;
      }
      resultData.push(item);
    }
  }
  return resultData;
}

Another option is to use the survey.getPlainData() function. It returns survey result data as an array of plain objects: with question title, name, value, and displayValue.

You may use modifySurveyResults function as modifySurveyResults(survey) instead of survey.data in survey.onComplete event.

Survey States (From 'running' to 'completed')

Survey may have five different states. To get the current state, check the state read-only property. This section describes all the survey states.

State 'empty'

If the survey model has no visible questions/pages, the survey is in the empty state. The widget shows a message that a survey is empty: "There is no visible page or question in the survey.". You can change this text like follows:

Survey.surveyStrings.emptySurvey = "The current survey is empty";

State 'loading'

If the SurveyJS loads a survey model from SurveyJS Service, the survey is in the loading state. The message about survey loading is showing. The widget shows a message that a survey is loading. You can change this text like follows:

Survey.surveyStrings.loadingSurvey = "Please wait. Your survey is loading…";

State 'starting'

SurveyJS can display a start page (with any introduction info about the survey, start button, etc.) before displaying the first survey page. Displaying a start page is necessary when you create a quiz (a limited to time survey).

Set the firstPageIsStarted property to true to show a start page instead a first survey page when a survey is loaded. An end user cannot come back to a start page after clicking the "start" button.

If the SurveyJS shows a start page, the survey is in the starting state.

You can change the startSurveyText property value to modify the "start" button text.

State 'running'

While survey pages (with "Previous", "Next" and "Complete" buttons) are displayed to an end user, the survey is in the running state.

State 'completed'

When a survey is completed:

  • the survey is in the completed state;
  • the survey displays a complete page;
  • the survey.onCompleted event is fired.

Complete Page

You can turn off the complete page by setting the showCompletedPage to false. When the complete page is disabled, the survey is still in the completed state, but the survey widget becomes invisible to end users.

Use the completedHtml property to specify the complete page's HTML. This property supports text preprocessing. To see how it works in action, refer to the Process Text example.

Replay Survey in Read-Only Mode

When the survey is completed, the onComplete event occurs. In most cases, this event is used to save the survey results in your own database.

However, you can show the same survey to an end user from the beginning, but in read-only mode:

survey.onComplete.add(function (sender, options) {
  // By default, the 'clear' method clears all data and go to the first page
  // Make a survey to keep the results by passing the first parameter as 'false'
  sender.clear(false);
  // Turn a survey into read-only mode
  sender.mode = "display";
});

Survey Data, Modify or View Survey Results

SurveyJS provides access to survey results. This can be helpful in the following cases:

  • make predefined answers to particular questions before the survey starts
  • review survey results
  • restore the answered questions if an end user leaves a survey incompleted
  • clear data for invisible questions
  • depending on question's answer, modify other question answers.

Survey Data API

Survey expose the surveymodel.data property, that contains survey results in JSON format question name: questions value.

Every question, except html question that does not have input, has a writable question.value property. The value property does not store its value. The actual question value is stored in survey.data. You can access a question value using the survey.getValue(name) and survey.setValue(name, newValue) functions.

Thus, the myQuestion.value code returns the same result as survey.getValue(myQuestion.name).

To be more precise, the question.name is used, unless question.valueName property is empty. We will talk about valueName property later, in one of described scenarios.

Predefined Answers

You may need to have predefined answers. For example, you need to have a default value for Boolean question as True. To specify a default value, use the question.defaultValue property. You can specify this property in JSON, or in our Survey Creator. After loading the JSON, on starting the survey, the defaultValue property is copied to the question.value property.

Tip

You can use the question.value property or survey.setValue(name, newValue) function to set the needed value in code at any time.

Review Survey Results

To review survey results, stored in your own data base, you can use a survey in read-only mode:

survey.data = JSON.parse(YourResultAsStringFromDatabase);
survey.mode = "display"; //set a survey to read-only mode

Restore Answered Questions for In-Completed Survey

When an end user does not complete a survey in a single session, and returns to a survey later, you can refill the survey results and a last visited page. You can save the incomplete results in your data base or in a browser local storage.

To save the incomplete results, set the survey.sendResultOnPageNext property to true. Each time an end user navigates the next page, the survey.onPartialSend event occurs.

The code sample below implements restoring answered questions and current page from a local browser storage.

survey.sendResultOnPageNext = true;
var storageName = "yourSurveyUniqueNameOrId";
function saveSurveyData(survey) {
  var data = survey.data;
  data.pageNo = survey.currentPageNo;
  window.localStorage.setItem(storageName, JSON.stringify(data));
}
survey.onPartialSend.add(function (survey) {
  saveSurveyData(survey);
});
survey.onComplete.add(function (survey, options) {
  saveSurveyData(survey);
});
var prevData = window.localStorage.getItem(storageName) || null;
if (prevData) {
  var data = JSON.parse(prevData);
  survey.data = data;
  if (data.pageNo) {
  survey.currentPageNo = data.pageNo;
  }
}

Example

Patient Medical History

Clear Data for Invisible Questions

SurveyJS clears values for invisible questions by default. To change this behavior, change the clearInvisibleValues property value to:

  • none - survey includes the invisible values into the survey data.
  • onHidden - survey clears the question value when the question becomes invisible. If a question has an answer value and it was invisible initially, a survey clears the value on completing. This option is useful if you have a cascade condition in visibleIf expressions.
  • onComplete (default) - survey removes property values of invisible questions on survey complete. In this case, the invisible questions will not be stored on the server.

Using Variables

SurveyJS allows you to use variables:

  • you can use variables in expressions and text processing,
  • variables are not used in questions and are not stored in survey data.

To create a new value or change its value, call survey.setVariable("variableName", value). Call survey.getVariable("variableName") to get the variable value.

On question.value Changed, Modify Other Questions or Change Their Values

In survey scenarios, changing a question value may require changing other questions.

Example 1. In the first question, you ask end users to select producers of cars they drove before. In the second question, you ask end users to select a car producer they like the most, from the car producers selected in the previous question.

Example 2. The first question is "Please select the language(s) you are speaking" and the second question "Please select the language(s) you want to learn". The choices from the second question do not contain selected choices from the first question.

Use the survey.onValueChanged event to implement this scenarios.

The code sample below implements the Example 2.

survey.onValueChanged.add(function(survey, options){
if(options.name !== "know") return;
knownChoices = options.question.choices;
var choices = [];
for(var i = 0; i < knownChoices.length; i ++) {
    var item = knownChoices[i];
    // the item is not selected
    if(options.value.indexOf(item.value) < 0) {
        choices.push(item);
    }
}
var learnQuestion = survey.getQuestionByName("learn");
learnQuestion.choices = choices;
learnQuestion.visible = choices.length > 0;
});

Refer to the Plunker snippet for the complete code sample.

Note:

The second scenario can be implemented without coding, by setting choicesVisibleIf property. Refer to the Dynamically Filter Choices, Columns and Rows section for more information.

Share the Same Data Between Two or More Questions

SurveyJS allows you to share data between different questions.

This may be useful in the following cases:

  1. Show the same question on different pages (for example, an end user enters their email on the first page, then confirms it on the last page).
  2. Create a complex form without additional coding (for example, an end user enters several items, moves to the next page and enters more details for each item).

Having the same question.name is not a good idea, those questions may be different and can have their own logic on showing/hiding or enabling/disabling. For this purpose, we have introduced question.valueName property. If this property is set, then question is using valueName property, instead of name property, to get/set its value from the survey data storage.

You can create complex forms without writing a single line of code. For example, you need to get an information about your user employees. On the first page, the user enters employee names, on the next page(s) the user enters additional information about each of them.

On the first page, you have a matrix dynamic question, with ability to add/delete rows and one column: Name. On the second page, you ask an additional information about employees using panel dynamic. It works fine, because for both questions the value is an array of objects.

Example

Sharing data between matrix dynamic and panel dynamic questions

Pages, Visibility and Navigation

Questions and panels (container) are located on pages. Every survey should have at least one visible page.

Page Visibility

The page is visible if:

  • the visible property equals to true (the default value),
  • the visibleIf property is empty (for more information about visibileIf expression, refer to the Conditions section),
  • its expression returns true and the page has at least one visible question.

SurveyJS doesn't show pages that have no visible questions, it skips them automatically.

Navigation

Page List

Use the following properties to get the survey pages:

  • survey.pages - returns a list of all pages;
  • survey.visiblePages - returns a list of visible pages. End users navigate visible pages and this array may be changed while a user runs a survey.

Current Page

Use the survey.currentPage property to get or set the current page. If a survey has no visible pages, this property returns null.

To change the current page from the code you may call:

survey.currentPage = myPage;

// or change the current page using visible page zero-based index
survey.currentPage = visiblePageIndex;  

// or change the current page by setting the page name
survey.currentPage = "myCurrentPage";

SurveyJS allows you to navigate survey pages in code:

  • to a previous page - call survey.prevPage();
  • to a next page - call survey.nextPage();
  • to complete a survey - call survey.completeLastPage().

The prevPage() function returns false and do not change a current page, if the current page is already the first page.

The nextPage() and completeLastPage() functions return false and do not go to the next page or complete a survey if there are any errors on the current page. An end user must fix them first to go further. Refer to Validation for more information.

SurveyJS exposes the following navigation events:

Set survey.showNavigationButtons to false to hide the default navigation buttons, and create your own navigation by using these functions and events.

Example

Custom Navigation

Here are additional properties that you may find useful:

  • showPrevButton - set it to false to hide the previous button. In this case, your users cannot comeback to the previous page
  • pagePrevText - specifies the previous button text
  • pageNextText - specifies the next button text
  • completeText - specifies the complete button text

Automatic Navigation

You can enable the automatic navigation by setting the goNextPageAutomatic property to true. In this case, a survey automatically goes to the next page when a user has answered all questions.

Example

Go to the next page automatically

Survey Progress

To show a progress bar, set the showProgressBar property to top or bottom. To change the default text: Page x of N, change the localization string Survey.defaultStrings.progressText, the default string for English localization is: "Page {0} of {1}".

All Questions on a Single Page

SurveyJS can display all the questions on a single page. It may be useful when you want your users to review their answers in read-only mode. Set the survey.isSinglePage property to true to display all the questions on a single page.

Skip Pages

SurveyJS allows you to set a visibility expression for individual pages, panels, and questions. If a page has no visible panels or questions, the page becomes invisible. SurveyJS automatically skips invisible pages. Refer to the next section for more information about visibility expressions.

Questions and Containers Conditional Visibility, Read-Only and Required Questions

SurveyJS allows you to implement custom logic in surveys. For example, you may need to ask different questions based on age, for loyal or unhappy customers, or you may make some questions read-only or required based on answers in other questions.

SurveyJS has a powerful and flexible expression engine powered by PEG.js parser generator.

Boolean Expressions

Questions, panels and pages have visibleIf, enableIf and requriedIf properties.

These properties are empty by default. Each element's behavior depends on the isVisible, isReadOnly and isRequired properties. The question containers (panel and page) become invisible if they have no visible questions.

Before rendering the first page, SurveyJS parses all boolean expressions (visibleIf, enableIf, and requriedIf), creates the expression trees, and run all expressions. Later, SurveyJS runs all expressions after any value change. If the expression returns false, the element becomes invisible (or read-only or non required), if it returns true – visible (enabled, required). The question values should be in braces: {yourQuestionValueName}.

Here are some examples of boolean expressions.

Expression Description
" >= 21" Returns true if the age question has value 21 or higher
"( + + ) > 21 and == ‘yes’" Use or and and operators, squares and arithmetic operations
"!( == ‘yes’ and ( + + ) > 21)" Use "!" or "not" to change the result on opposite
" notempty" Returns true if name has a value
empty Returns true if name has no value
" = [‘English’, ‘Spanish’]" Returns true, if a user selects these two valus in speakinglanguages question. It is typically a checkbox.
" contains ‘Spanish’" Returns true, if a user select 'Spanish' in checkbox. They may or may not select other values.
age() >= 21 Returns true, if function age returns 21 and greater. The function age calculates the age based on the birth date and the current date.

If your question has complex values, then you may use dot "." to access the child value.

  • multiple text -
  • matrix -
  • matrix dropdown -

To access the question value inside the panel dynamic, use the following syntax: {dynamicpanelname[index].questionname}, where index is zero-based.

To access the cell value of the matrix dynamic, write the following code: {matrix[index].columnname}, where index is zero-based.

Cell Visibility in Matrix and Dynamic Panel Questions

You can make a cell in a matrix question invisible or disabled based on other cells value on the same row. In this case, use the prefix row to access a cell value on the same row: {row.columnname}.

You can use the same approach in dynamic panels. To access questions value on the same panel in the expression, use the panel prefix: {panel.questionName}.

Use Functions in Expressions

SurveyJS expressions support functions with unlimited parameter number. SurveyJS library implements a set of built-in functions, like age or iif: age({birthdate}) >= 21

The code sample below illustrates how to use the age function:

// The age() function accepts a birth date
// and returns a number of full years
function age(params) {
  if (!params && params.length < 1) return -1;
  var birthDay = new Date(params[0]);
  var ageDifMs = Date.now() - birthDay.getTime();
  var ageDate = new Date(ageDifMs); // milliseconds from epoch
  return Math.abs(ageDate.getUTCFullYear() - 1970);
}
// Register the function for use in SurveyJS expressions
Survey.FunctionFactory.Instance.register("age", age);

You may write, register, and use your own functions.

Starting with v1.0.21, you can access to your survey object as this.survey inside a custom function.

As result you may, for example, pass a question name to your function: myFunc('myQuestionName') and then get it as:

questionInstance = this.survey.getQuestionByName(params[0]);

The table below demonstrates a list of built-in functions:

Function name Description
age({birthdate}) Returns the age by birth date.
iif("expression", trueValue, falseValue) Returns trueValue if expression returns true and falseValue if expression returns false.
iif({question1} + {question2} > 20, 'high', 'low')
isContainerReady("panelname/pagename") Returns true, if all questions in container (panel or page) are answered correctly. It validates (silently) all questions recursively in the container. If there is an error it returns false, otherwise true. If a question value is empty, but it does not have validators and it is not required then validation would pass successful.
isDisplayMode() Returns true if the survey is in display mode. Here is the example of usage: isDisplayMode() <> true
sum(par1, par2, ...) Returns the summary of passed parameters.
max(par1, par2, ...) Returns the maximum of passed parameters. from v1.5.19
min(par1, par2, ...) Returns the minimum of passed parameters. from v1.5.19
avg(par1, par2, ...) Returns the average value for passed parameters.
sumInArray({questionName}, 'propertyName') Returns the summary for array of objects by property 'propertyName'. sumInArray('matrixdynamic', 'total') > 1000
avgInArray({questionName}, 'propertyName') Returns the average value for array of objects by property 'propertyName'. avgInArray('matrixdynamic', 'quantity') > 4
minInArray({questionName}, 'propertyName') Returns the minimum value for array of objects by property 'propertyName'. minInArray('matrixdynamic', 'quantity') > 1
maxInArray({questionName}, 'propertyName') Returns the maximum value for array of objects by property 'propertyName'. maxInArray('matrixdynamic', 'quantity') > 10

If you feel there is a need in a particular function, then write us about it.

Using Asynchronous Functions in Expressions

You may need to make some calculation or return a result from a server. SurveyJS has to make a request to a web service, wait until it gets the result, and continue evaluate the expression. Calling and getting the result from a web service is an asynchronous operation. If there is one asynchronous operation in your flow, then all operations that use it should be asynchronous too.

The current version of SurveyJS allows you to register an asynchronous custom function. SurveyJS uses a callback approach to support ECMA Script 5 (IE).

The code sample below illustrates an asynchronous function example:

 function asyncFunc(params: any): any {
   var self = this; // Store the context for this.returnResult callback
   setTimeout(function() {
       // Return the value via a callback
       self.returnResult(yourValue)
    }, 100);
    return false; // The return value is ignored.
  }
  // The third parameter specifies that the function is asynchronous
  FunctionFactory.Instance.register("asyncFunc", asyncFunc, true);

The code sample below demonstrates how to add and register a custom asynchronous function (isCountryExist). This function is used in an expression validator.

async function isCountryExist(params) {
  if (params.length < 1) {
    this.returnResult(false);
      return false;
  }
  var countryName = params[0];
  var self = this;
  var res = await $.ajax({
    url: "https://restcountries.eu/rest/v2/all"
  }).then(function(data) {
    var found = false;
    var countries = data;
    for (var i = 0; i < countries.length; i++) {
      if (countries[i].name == countryName) {
        found = true;
        break;
      }
    }
    self.returnResult(found);
  });
  return false;
}
Survey.FunctionFactory.Instance.register(
  "isCountryExist",
  isCountryExist,
  true
);

// Example of using
var json = {
  questions: [
    {
      type: "text",
      name: "country",
      title: "Type a country:",
      validators: [
        {
          type: "expression",
          expression: "isCountryExist({country}) = true",
          text: "Please type the country correctly!"
        }
      ]
    }
  ]
};
var survey = new Survey.Survey(json);

Example

Async Function in Expression.

Cascade Conditions

Example. The first question is "Do you have children?" (hasChildren) and the second question is "How many children do you have?" (kidsCount). The second question has the following visbileIf expression: "{hasChildren} = 'yes'". Then you display dropdowns with questions: "The first kid age", "The second kid age" and so on. Their visibleIf expressions are as follows:

"{hasChildren} = 'yes' and {kidsCount} >= 1",

"{hasChildren} = 'yes' and kidsCount >= 2" and so on.

In this example, the additional {hasChildren} = 'yes' condition is added to "{kidsCount} >= 1", because of the following:

  1. A user answers the "Do you have children?" question 'yes' and "How many children do you have?" to 2.
  2. A user answers the first question 'no'.
  3. The second question becomes invisible, but its value is still 2 and the questions about kids' age are still shown, unless you add "{hasChildren} = 'yes'" condition.

SurveyJS allows you to avoid additional conditions in cascade questions. Set the survey.clearInvisibleValues property to onHidden to clear values for invisible questions.

In the example above, on making "How many children do you have?" question invisible, its value would be cleared. As a result, the value becomes undefined and you can simplify the expression to: "{kidsCount} >=1".

You can play with the Cascade Conditions example to see the survey.clearInvisibleValues property use in action.

Dynamically Filter Choices, Columns, and Rows

SurveyJS allows you to control which answer options are visible based on previous choices in a survey.

Method #1: Specify Visibility Conditions for Individual Options

Example. A user can select multiple communication channel options. The "Text Messages" and "WhatsApp" options appear only if a user has entered their phone number in a previous question.

You can implement this behavior without writing any code. SurveyJS exposes the visibleIf property for answer choices:

choices: [
    "Email",
    { value: "Text Messages", visibleIf: "{phone} notempty"},
    { value: "WhatsApp", visibleIf: "{phone} notempty"}
  ]

Method #2: Display Options Selected in Previous Questions

Questions in this example progressively filter out browsers based on user answers.

Here's the logic breakdown.

  • Display the complete browser list.

    name: "installed",
    choices: ["Chrome", "MS Edge", "FireFox", "Internet Explorer", "Safari", "Opera"]
    
  • Display only browsers checked in the previous question.

    name: "default",
    choicesVisibleIf: "{installed} contains {item}",
    choices: ["Chrome", "MS Edge", "FireFox", "Internet Explorer", "Safari", "Opera"]
    

    SurveyJS iterates all "choices" and substitutes each as an "" into choicesVisibleIf. Only choices that make the expression true appear in the list.

  • Display browsers checked in #1, exclude browser that matches #2.

    name: "secondChoice",
    choicesVisibleIf: "{installed} contains {item} and {item} != {default}",
    choices: ["Chrome", "MS Edge", "FireFox", "Internet Explorer", "Safari", "Opera"]
    

Examples

Fill the Choices From a Restful Service

SurveyJS can populate choices/items in a drop-down list, check boxes, and radio groups with items obtained from a web service.

Example

Get choices from a web service

The online Survey Creator allows you to configure a connection to a web service with a dialog:

Choices By Url Property Editor

Choices By Url Property Editor

Property Name Description
url A link to a web service. You may use the text preprocessing here. For example, the following url: https://restcountries.eu/rest/v2/region/{region} is changed based on the region question value. SurveyJS automatically gets data from web service on changing the region value.
path Use this property, if a web service returns a lot of information and you need only a part of it. For example, the service returns the list of countries and list of capitals. If you need a list of countries, set a correct path from which SurveyJS obtains the data, like: DataList1\DataList2
valueName The property name in your obtained data, that SurveyJS should bind with the value.
titleName The property name in your obtained data, that SurveyJS should bind with the text. It can be empty.

Note

During the user session, if the same URL is requested, SurveyJS returns data from a cached list and does not send another request.

You can control the process of setting choices into a question from the web service by handing the onLoadChoicesFromServer event. The options parameter in this event has three properties:

  • question - the question where choices are loaded
  • choices - the list of loaded choices that library fills automatically
  • surveyResult - the result object that comes from the web service

Readonly and EnableIf Expression

Questions, matrix dropdown, and matrix dynamic columns have the enableIf property. It works exactly like visibleIf, except it makes control enable/disable instead of visible/invisible. It is useful when you do not want to change your layout and want to make sure that all questions are always visible, but still want to make it impossible for your users to answer some questions.

Example

Condition - Enable/Disable Elements

Since v1.0.31, we have introduced the readOnly and enableIf property into Panel and Page objects. They work like the same properties in Question object. The only difference, since these objects are containers, then all children (Panels and Questions) inside them becomes read-only if their parent is read-only.

Text Processing, Dynamic Titles, and HTML Properties

The following survey elements support text processing:

  • pages,
  • panels,
  • question titles,
  • question description,
  • survey completedHtml and loadingHtml properties,
  • html property in html question.

It means you can set a question title as: "{name}, could you please provide us your e-mail?", where the name is the question name or a calculated value name.

Note

SurveyJS uses a question's display name. In questions, like dropdown, the display name and value name may differ (e.g., value can be "UK" and the display name is "United Kingdom").

Question Numbers

You can control the question numbering. All questions titles show question numbers by default: from 1 to the visible question number in the survey. You can hide question numbers by setting survey.showQuestionNumbers property to off, or start the numbering from the beginning on each page, by setting this property to onPage.

You may use alphabet numbering by setting survey.questionStartIndex property to A. or a.. You can add prefix and change the postfix (default is dot) for this property, for example: # (1) or (A).

Question Required Mark

Use the survey.requiredText property to change the required symbol. SurveyJS uses the asterisk (*) symbol by default. You can change it to another text or make it empty.

Example

Process Text

Calculated Values

Since v1.1.10 you may use calculated values in your text processing. Calculated Value item has three writable properties:

  • name (it should be unique),
  • expression (value read-only property is calculated based on this expression),
  • includeIntoResult (a Boolean property, false by default. Set it to true, to include it into survey.data). It has one read-only property: value (calculated automatically based on expression).

Example

Use calculated values

Client and Server-Side Validation

Before proceeding to the next page or before completing the survey, the SurveyJS Library validates all questions on the current page. If there is an error, the current page is not changed, all errors are shown and the input, the first of invalid questions is focused.

If you want to validate the value and display an error immediately after a user entered the value into the question, change the survey.checkErrorsMode property from the default onNextPage to onValueChanged.

survey.checkErrorsMode = "onValueChanged";

Since v1.1.10, SurveyJS supports async expressions. You may add your own async custom functions into the library that your users can use to create surveys.

Standard Validators

The simplest and most used validation is a required value. You must set question.isRequired to true and SurveyJS will require the user answer the question. In SurveyJS Creator, toggle exclamation mark (!) to make a question required. To override the error text on required error, change the survey requiredText property.

Except required validation, there is a list of built-in validation classes, that you may use by adding them into question.validators array property. For example, the following code adds a validation for e-mail input:

question.validators.push(new Survey.EmailValidator());

The same code in JSON will be as:

validators: [{ type: "email"}]

To change the default error text, you must set the validator text property.

Here is the list of standard validators

Name Validator Class Description
numeric NumericValidator Raises an error if the question answer is not a number, or if an entered number is outside the minValue and maxValue range.
text TextValidator Raises an error the entered text length is outside the minLength and maxLength range.
expression ExpressionValidator Raises an error when the expression returns false. Use the expression property to specify the validated expression. This validator was added in v1.0.23.
The following expression validator raises error if the summary is less then 100: expression: "{price} \* {quantity} >= 100".
answercount AnswerCountValidator Works for questions which value is array, for example: checkbox. Raises an error if a user selects less choices that minCount (if minCount defined) or more than maxCount (if maxCount is defined).
regex RegexValidator Raises an error, if the entered value it does not fit the regular expression defined in the regex property.
email EmailValidator Raises an error, if the entered value is not a valid e-mail.

Example

Custom Validation

SurveyJS allows you to handle the onValidateQuestion event to implement custom validation logic.

The following code demonstrates how to display an error message if the value in rateMe is not in the rage from 1 to 9.

survey.onValidateQuestion.add(function(sender, options) {
  if(options.name == "rateMe") {
    if(options.value < 1 || options.value > 9) options.error = "Please enter value from 1 till 9.";
  }
});

Example

Event Validators.

Custom Validators

You may implement your own validator, if you want to use it in SurveyJS Creator, for example, or going to use it in your surveys.

Example

Custom Validators.

Validate Results on Server

Sometimes, there is no way you may validate the answers on the client and validation should be performed on your backend or you must call an ajax function to get an additional information.

Example

Server Validators.

survey.onServerValidateQuestions.add(function(sender, options) {
// question values on the current page have the following format: 'questionName: value'
// Send the 'options.data' json object to your server.
// To specify errors on the current page, set the 'options.errors' json object as "questionName": "ErrorText".
// Leave it empty, if there is no error on the current page.
// Call the 'options.complete()' function to tell the survey that your server callback has been processed

    // options.data contains the data for the current page.
    var countryName = options.data["country"];
    // If the question is empty then do nothing
    if (!countryName)
        options.complete();

    //call the ajax method
    $
        .ajax({url: "https://restcountries.eu/rest/v2/all"})
        .then(function (data) {
            var found = false;
            var countries = data;
            for (var i = 0; i < countries.length; i++) {
                if (countries[i].name == countryName) {
                    found = true;
                    break;
                }
            }
            //if the country is unknown, add the error
            if (!found)
                options.errors["country"] = "The country name '" + countryName + "' is not in this list: https://restcountries.eu/rest/v2/all";

            //tell survey that we are done with the server validation
            options.complete();
        });
});

Localization and Multilanguage Support

At the current moment, the SurveyJS strings are translated to 34 languages.

Use the survey.locale property in runtime to change the survey locale.

// Sets Spanish locale
survey.locale="es";

To see the list of all available translations, open the SurveyJS Creator, click on Survey Settings button, and open the Default Language drop down.

The localization is supported by the community. If any strings are not translated to your language, or you want to translate them in a different way, you can change the translation locally:

var myloc = Survey.surveyLocalization.locales["localename"];
myloc.stringName = "My New Localized string";

You can find the list of all the localized strings in the default English localization.

To localize SurveyJS to your own language, read the instruction in the Localization file.

Create a Multilanguage Survey

SurveyJS allows you to create a single survey for multiple languages at a same time. To switch between locales, change the survey.locale property.

All strings in JSON have the following declaration:

text: "Some text"

Most of strings in SurveyJS are localizable and you may write in JSON. In the following example, This localizable string will return "Dog" for all languages, except German. For German (de) locale it returns "Der Hund":

text: { "default": "Dog", "de": "Der Hund" }

Note, that text: {"default: "Dog"} is the same as: text: "Dog".

If you want to get/set strings into default locale (in code, or in Survey Creator), then set survey.locale to empty string. For example, if you want to get/set strings into Spanish locale, then set survey survey.locale into "es" (Spanish).

Example

Multilanguages demo.

Extend SurveyJS Elements by Adding Properties

Since this topic is mostly for our Survey Creator users, it is described in the Survey Creator Documentation. However, for some scenarios, the described functionality maybe useful for SurveyJS Library without using the Creator.

Triggers: Control the Survey Logic

SurveyJS triggers help you to implement some logic in your surveys without writing JS code.

Every trigger has the expression property. On changing a value, if this value is used in the expression, then the expression is running. If the expression returns true, then the trigger executes the function, a success function, that make a change(s) in the survey logic.

Every trigger type overrides this success function in its own way.

Available Triggers


complete

Complete the survey if the expression returns true. It performs on changing the current page into the next.
The following trigger completes the survey if the question "age" on this page will have value less than 18.

{ "type": "complete", "expression": "{age} < 18" }

setvalue

If expression returns true, then copy a value from the setValue property into the setToName value/question.
The following triggers set the value "ageType" to child or adult based on the "age" question.

[{ type: "setvalue", expression: "{age} < 18", setToName: "ageType", setValue: "child" },
 { type: "setvalue", expression: "{age} >= 18", setToName: "ageType", setValue: "adult" }]

copyvalue

It works like the setvalue trigger. It takes a value from a question fromName and copy it into setToName.
The following trigger copies the billing address into delivery address if the question "Shipping address same as billing" is set to "Yes".

{ "type": "copyvalue", "expression": "{sameAsBilling} = 'Yes'", setToName: "shippingAddress", fromName: "billingAddress" }

runexpression

If the expression is successful, then it runs the expression in the runExpression property. If the property setToName is not empty, then the result of the runExpression would be set into this value.
Here is the example of using this trigger.


visible

Obsolete, use the visibleIf property instead.