The question of pre-populating a select_one (or select_multi) with a desired option has come up a few times in the past - eg Set a default choice for single-select, Randomly Selecting One Option by default - Not working, and most recently First choice selected by default (select_one).
Although, like any question, you can always manually add a value in the 'default' column of a select question, this is a bit ungainly and requires you to manually copy one of your option values (important: not the label!) over, and if you ever change these options in your form you have to remember to also go back and manually edit the default value. A better solution would be to be able to prepopulate the select with, say, the first option - whatever it may be.
Always up for a challenge (and undeterred by @Grzesiek2010's assertion: "The only option is to use default 2 and put there your first option in each question but that's it" )...
Pre-populating select_one / select_multiple With Default Option
Here is a trick you can use to programmatically pre-populate a select_one or select_multiple with the first (or in fact any!) option, without having to manually copy the desired option value into the default.
Actually, its 2 tricks:
-
The first is to force pyxform to turn your select option list into a secondary instance. This can be accomplished by adding a redundant choice_filter into your select. Normally a choice_filter is used for cascading selects, but it also has the useful side-effect of 'instance-izing' your option list into a separate instance XML in your XForm, which you can then lookup things using regular XPath expressions [this trick originally courtesy @LN ]. I use a simple choice_filter that simply returns everything:
choice_filter: name != ''
-
Now that you have your select options accessible in this secondary instance, you can use a once() calculation to populate your select with a value, in this case your desired option value, which you lookup with a somewhat cyptic XPath command:
once(instance('options')/root/item[position()=1]/name)
Deciphering:
-
instance('options')/root
references the XML secondary instance that the choice_filter created containing your option list. -
/item[position()=1]
selects the first option item. Or if you want to pre-populate with the 3rd option this would beitem[position()=3]
-
/name
selects the option value (as opposed to the option label) which is needed to correctly populate the initial select result.
The once()
function effectively only fires when the current select result is null/empty, so it will set the initial select value to your chosen option, but then wont keep overwriting (with the default) if you subsequently select other things, or unselect the default.
This technique works for both select_one or select_multi. The following form implements both. Have a play around, eg in XLSForm Online, and let me know what you think.
selectdefault.xlsx (9.8 KB)
selectdefault.xml (2.5 KB)