Last updated July 24, 2018
When you create a new survey using Survey123 Connect, a new feature service is created on the fly on your behalf. Some of you wonder how the different XLSForm types of questions in your form are mapped into esri field types in the feature service. In this post I will describe how XLSForm types are mapped into esri fields by default, but we will also describe how you can take control and tell Survey123 how to best do the mapping and even add fields in the database that are not shown as questions in your form.
The type of XLSForm question is defined in the Type column in your Choices worksheet. Here are the default mappings to esri field types.
Esri Field Type (default mapping)
esriFieldTypeGeometry (point, WGS84, 4326)
Survey123 Connect v.184.108.40.206 and newer include support for the bind::esri:fieldType and bind:esri:fieldLength columns in the survey worksheet. Adding values in these columns is optional, but extremely useful when you want to control exactly the type of field to be created in ArcGIS for your survey questions.
Some question types are a no brainer. For example, if you have an integer or decimal question, Survey123 Connect will automatically translate them into esriFieldTypeInteger and esriFieldTypeDouble respectively. You will probably not want to overwrite that behavior.
However, select_one questions are trickier. Up until v 1.0.135 Connect would always map select_one questions as esriFieldTypeString. If you happen to use a choice list that stores integers then you will want to be explicit, and force your select_one to be mapped into a geodatabase column of type integer.
The same applies to other questions such as select_multiple and calculates. So far Survey123 Connect would always map them to esriFieldTypeString columns, but now you can have more control.
The list of values supported in the bind::esri.fieldType column are:
One important warning is that Survey123 Connect will not be able to validate your choices. For example, if you have a calculation expression that returns a string and you set the calculate question to esriFieldTypeInteger… well… things will not go well when the end user tries to submit the data. The same applies to select_ones: say that among all your choices one of them is a string and you mapped the question to esriFieldTypeInteger… that is a perfect recipe for a disaster because ArcGIS will not be able to cast the selected string into an integer value.
The null value was added in version 2.4 and allows you to add a question to your survey that has no representation in the feature service. There are multiple scenarios where this could be handy. For example, say you want to ask for the year in which a building was built (date type of question with a year appearance), but you want to actually store the age of the building. Well, then you set the yearbuilt question as null in the esriFieldType column, and then you use a hidden type of question with a calculation to persist in the feature service the age. Check out The Power of Nothing blog post for a more detailed discussion on the null type.
The second column that Connect now supports is called bind::esri:fieldLength. This column is useful to restrict the length of fields as you can imagine. It really has a double effect. First, it sets the maximum length of the field in the geodatabase, but additionally, it will limit the number of characters that the user will be able to input in the question. For example, say that you want people to input a US ZIP code. We know that ZIP codes are made out of 5 numeric values. So if you set the length of the field to 5, then users will not be able to input 6 or more characters in the app. You may also want to use bind::esri:fieldLength to expand the number of characters allowed in a text question. By default text fields are mapped into esriFieldString columns with 255 characters, but what it you want users to enter up to 1000? You would simply set the value in this column to 1000.
The bind:esri.fieldLength column is optional as well and makes more sense to use when using questions that will be stored as esriFieldTypeInteger , esriFieldTypeString or esriFieldTypeDouble.
Adding columns without adding questions in the form:
Say you want to add fields in your feature service, but not show them in the form. Say, even, that you want to add fields and put values in them without the user having to do anything.
There are a few techniques for this:
- Calculate: You can use a calculate type of question. Calculate questions are never shown in the form, but we will create a field in the feature service for them. A calculate always requires you to set an expression in the Calculation column. The advantage of calculates is that you can pre-populate values and these values can be dynamic depending on answers in the form. By default, all calculates are mapped as esriFieldTypeString columns, but you can use the bind::esri:fieldType column to use your own mappings.
- Hidden: Like calculates, it is a type of question. Hidden questions are in fact very close to calculates, except that they do not require you to fill the calculation column. You could for example leave the value of the field blank, or use a default. Like with Calculates, Hidden questions are by default mapped to esriFieldTypeString, but you can overwrite that.
- Relevant: Use a relevant expression that always evaluates to false and your question will not show up in the form. However, Survey123 will always create the corresponding field in the feature service. This is easy to do, but has two disadvantages: you cannot pre-populate values in the field and it adds an overhead to the form because we need to evaluate the expression in the relevant column. One unique use case that you can satisfy with relevant expression is when you want to create a new field and associate a coded value domain with it in ArcGIS. In this case, using a relevant is your only choice. Lets be clear, this is a hack. A bad hack!
When using a Calculate or a Hidden question, the bind::esri:fieldType column described in this post will come very handy. Even when using relevants, setting your own mapping may make sense when using Select_One questions.