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"},
]",
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?
My ideal survey design would include:
In the Excel:
In the app:
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.
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:
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.
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.
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.
I think this would be enough for the users and be way easier and more stable.
Just an idea.
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.