Survey123: Compile repeat entries with JS

351
5
03-07-2024 04:27 PM
EM-wsp
by
New Contributor II

Hi!

I have a checklist survey with hundreds of questions. To have them all together in the S123 form I would need to have a table in db with hungreds of fields where each question corresponds to each field. It is undesirable.

Another approach would be to have each question as a record in a child table with just three fields: globalid, question, answer. This is better from data model perspective, but makes the S123 form very akward as a user would need to add a separate repeat for each question and could not see them all together.

I am trying to see if there is a way to combine advantages of these two approaches, having questions in the survey all together but get them submitted as repeats.

My idea is to create a list of dummy questions of 'null' type. And then to use a JS function to compile those answers into a repeat-like JSON item. So it immitates repeats in a JSON format at data submission.

The problem is that S123 puts "" around the JSON string returned by my JS  function interpreting it to be a text (see the example below). Is there any way to take away these quotation marks?

I know that I want to go against S123 rules here, but we really need a solution. Please, let me know if you see any other way to do it.

 

 

"RealRepeat": [
  {"question": "question_1", "answer": "answer_1"},
  {"question": "question_2", "answer": "answer_2"},
],
"MyRepeatImmitator": "[
  {"question": "question_1", "answer": "answer_1"},
  {"question": "question_2", "answer": "answer_2"},
]",

 

 

0 Kudos
5 Replies
ChristopherCounsell
MVP Regular Contributor

Can you share more around your survey form and workflow? We may be able to suggest a better design approach than a rather specific JS based solution.

Survey123 can interpret repeat data as Arrays in JavaScript. You have a lot of power here before returning the data to the form for submission. I've done this to return text at html and it doesn't come back with quotations.

Can you share the JavaScript function?

0 Kudos
EM-wsp
by
New Contributor II

My ideal survey design would include:

  • a multiple-choice field where I have all my checklist questions as choices. So if yes, a user checks in the question.
  • a calculation field which uses a JS function to construct a repeat-like array from the checked-in questions from the multiple-choice field, so when this array gets submitted to the feature service it will be interpreted as an array of repeats and populate the child table with them.

In the Excel:

EMwsp_0-1709930128652.png

In the app:

EMwsp_1-1709930334663.png

JS function:

function dataForRepeat(checklist){
    let questions = checklist.toString().split(","), repeat_array = [];
    questions.forEach(x => repeat_array = repeat_array.concat({'question': x, 'answer': 'Yes'}));
    console.log(repeat_array); // returns [{"question":"question_1", "answer":"Yes"}, {"question":"question_2", "answer":"Yes"}]
    return repeat_array; //returns in S123 JSONstring - myRepeatImmitator: "[object object]"
    return JSON.stringify(repeat_array); //returns in S123 JSONstring - myRepeatImmitator: "[{\"question\":\"question_1\",\"answer\":\"Yes\"}, {\"question\":\"question_2\",\"answer\":\"Yes\"}]"
};

What I hope to achive is that in S123 JSONstring I get:

"MyRepeatImmitator": [
  {"question": "question_1", "answer": "Yes"},
  {"question": "question_2", "answer": "Yes"},
],

I don't know if it's possible. I will be happy to get any suggestions for this or other possible solutions. 

0 Kudos
ChristopherCounsell
MVP Regular Contributor

a calculation field which uses a JS function to construct a repeat-like array from the checked-in questions from the multiple-choice field, so when this array gets submitted to the feature service it will be interpreted as an array of repeats and populate the child table with them.

I don't believe this is possible and am not aware of anyone who has pursued this line of thinking before. It sounds like you are actively trying to circumvent both the Survey123 / XLSForm design construct and the apply edits request that gets sent to the feature service. Even if you pull this off I imagine you'll be prone to future issues.

It is possible to use JavaScript to parse repeat data into fields. Most often this is used for summary calculations or text compilations. The results are shown as notes or submitted as individual answers, i.e. against a field. You could do this to populate several fields, and have that submitted as your 'array'. I only do this when I have to and even then I try to keep it as cosmetic - complexity is better post data collection.

So... you have a list of 100 questions that are yes/no. Say they are a checklist for an issue/defect being present. You might have 10 defects out of 100. Instead of one row entry with 10/100 fields populated as yes, you want to pivot the questions into a repeat, so that all 10 defects are submitted as related entries with Issue (question) as a value in a second field.

In Survey123 terms the question is how to I calculate multiple hidden repeat entries. I don't believe this is possible, even with the use of JavaScript functions. You could do something like set a minimum repeat count based on the number of multiple choices selected, but then pre-populating the data in the repeat gets a bit weird.

Simpler design practices you could pursue:

  • Have the users enter a repeat for each issue present. Repeat summaries could be used to show what they have identified - and possibly what they have not - effectively becoming a checklist but being a bit more reliant on end users.
  • One or more multiple select questions to cover all 100 yes/no. No repeat. Less fields. Fieldlength just has to be large enough to allow if they selected all answers.
    • You could post-process this using ArcGIS Notebooks to add records to a related table by parsing the list that gets sent through the field value. Have a hidden 'Processed=no' field in the survey. Create the survey with the repeat (to make the table) but then drop the repeat from the questionnaire.

The second option sounds best for you - great user experience, simple survey design, with a basic post-processing of data that can be scheduled to run every 15 minutes. Less technical debt and complexity into the future; if it breaks, the data is still in the survey submission as a string list.

0 Kudos
DougBrowning
MVP Esteemed Contributor

What I do is have a rolling summary at the bottom using a join().  I also have summary pages at the end.

Like here under the QA/QC group I have a running list of all species added so far.

DougBrowning_0-1709908242269.png

Here is a Summary page with totals, avgs, min, max, etc and even Red warnings when things are off.  It uses a grid to make is compact and easy to read.

DougBrowning_1-1709908331025.png

I think this would be enough for the users and be way easier and more stable.

Just an idea.

 

0 Kudos
EM-wsp
by
New Contributor II

Thank you very much for your reply!

Repeats summaries are very good and helpful, but in my case the most of a trouble is the process of data entering through the repeats. I would have only two fields in the repeat - question and answer. The question would be selected through the dropdown list. It implies a lot of additional clicks as well as a risk that a user might skip some questions. Then the question list is really long... I cannot imagine adding hundred questions like that.

0 Kudos