ODK Advanced Workbook Structure by Dr. Caroline Krafft
In this advanced workbook structure guide by Dr. Caroline Krafft from St. Catherine University, learn about assigning variables, internal assignment of variables, member prompts, assigning age, JavaScript formulas, CSV integration, dealing with complex choice sets, and more. Explore step-by-step instructions and examples to enhance your ODK survey skills effectively.
Download Presentation

Please find below an Image/Link to download the presentation.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.
E N D
Presentation Transcript
1 ODK Advanced Workbook Structure Dr. Caroline Krafft St. Catherine University cgkrafft@stkate.edu Version: January 19, 2018
3 Assign Assign: Used for internal assignment of a variable For example, let s say we want to ask year of birth and calculate age More advanced/complex calculations, especially those used repeatedly (example: defining someone who was ever a wage worker) can go in the calculates sheet https://www.w3schools.com/js/default.asp is a handy repository of javascript formulas and tutorials
4 Section 2: Member prompts In section 2 we can put in prompts about different household members. Let s do this for the head of household Delete the current question Add a note: Information about the household head Add q201 to ask about (display.prompt.text:) year of birth (type: integer) Now we can assign an (approximate) age based on the year of birth
5 Assigning age Let s define age as an type: assign, name: q202 Assign requires an additional column in the survey (section) sheet: calculation We have to use JavaScript formulas for calculation for assign: (2018-(data('q201'))) 2018-the year in q201 We can then display this age Type: note, name: q202_note, display.prompt.text: Age: {{data.q202}} {{data.q202}} is how you call data to display, distinct from calculation We also have to add a new sheet, called model It has type and name columns, like survey, but for assigned variables Type: integer, name: q202
6 Convert and test Can navigate to the year of birth and check that it calculated age correctly
b. Calling on csv through a query & choice filters
8 Dealing with complex sets of choices So far we have been using very simple choices in the select questions (yes no) Some questions will have large or multi-level choices Example: Occupation codes Complex choices can be stored in a csv Then called on by ODK We are going to test this for two occupation levels In ODK Advanced Workbook Structure Solution, there is a csv named occupation.csv Note the column headers (oc1, oc2) as these will be key to calling data
9 Location of csv files ODK finds things very specifically in the directory structure Csv files that go with a particular form should be in the same exact folder as that form Copy occupation.csv from ODK Advanced Workbook Structure Solution abc to where the firstForm.xlsx file is app-designer/app/config/tables/firstForm/forms/firstForm
10 Querying the csv To pull choices from the csv we need to add a new sheet to our Excel: queries This sheet will (for now) have column headers: query_name, query_type, uri, callback New row query_name: occupation_csv, query_type: csv, uri: occupation.csv callback: _.chain(context).pluck('oc1').uniq().map(function(oc1){ return {name:oc1, label:oc1, data_value:oc1, display: {title: {text: oc1} } }; }).value() JavaScript to get the occupation data and keep unique values only of oc1
11 Adding the question for the query Let s add a question for occupation to section2 Add a note: Occupation Add a type: select_one_dropdown, values_list: occupation_csv, name: oc1, display.prompt.text: Level 1
12 Convert and test Navigate to the occupation Test choosing an occupation
13 Choice filters Next we want to show the second level of the occupation, nested to show only those within the first. This requires a choice filter Basic idea of choice filters: limiting choices based on responses to previous questions Very helpful with complex multi-level lists
14 Query for second level of occupation In the queries sheet query_name: occupation2_csv, query_type: csv, uri: gov.csv callback: _.map(context, function(place){ place.name = place.oc2; place.label = place.oc2; place.data_value = place.name; place.display = {title: {text: place.label} }; return place; }) Creates a map of occupations
15 Question for occupation 2 Let s add the second level of occupation to section2 Add a type: select_one_dropdown, values_list: occupation2_csv, name: oc2, display.prompt.text: Level 2
16 Choice filters for kism and shyakha Add a new column to the section2 sheet: choice_filter We want to only see the second level of occupation within the first In the Level 2 line, choice filter: choice_item.oc1 === data( oc1 ) Refer to the previous level of occupation and require that the answer be the same as that response for this level s options
17 Convert and test Navigate to occupations Should see only options within level 1 for level 2
19 Subforms Often dealing with nested relationships/questions Individuals within a household Fields within a farm Want to collect data on both levels Household and individual questions Want to link data across levels Example: ask questions about family enterprise only if at least one individual was self-employed or an employer Can do this with subforms This is one of the critical features of ODK 2.0
20 Structure of subforms Subforms are, effectively, their own forms Have their own folders within tables Use the same Excel worksheet setup Need to be XLSXconverted Additional features: Use model sheet to feed data from other forms Do NOT get added to framework Instead called from within main form Using linked_table functionality
21 A subform for household members We are going to make a subform about household members Navigate to app-designer/app/config/tables and Create a new folder: hh_member Create a new folder within hh_member: forms Create a new folder within forms: hh_member Save a (blank) Excel into that folder, named hh_member
22 Subform settings Copy the settings sheet from firstForm Change the form_id and table_id to: hh_member Change the survey display.title.text: Household members Delete the section 1, section 2 Change instance_name to: name This will be created within the survey
23 Subform survey Create a new sheet: survey Add the usual: type, values_list, name, display.prompt.text We are going to just show the household id and ask the name and sex, but you could add a long set of questions about individuals New row, type: note, display.prompt.text: Data for household {{data.hhid}} New row, type: text, name: name, display.prompt.text: Name of individual: New row, type: select_one, name: sex, display.prompt.text: Sex of {{data.name}}:, values_list: sex
24 Subform choices Need to create choices sheet, enter choices for sex New row, choice_list_name: sex, data_value: = 1 , display.title.text: male New row, choice_list_name: sex, data_value: = 2 , display.title.text: female
25 Subform model Add model sheet Columns: name, type In the model sheet, put in things that are created in another form (here, hhid being pulled in) Name: hhid, type: text
26 Main survey: adding subform Change the type of hhid to be text in section1 This helps the query/linking Let s add a new section, section3, for our new subform Update settings sheet by inserting a row below section2, copying the section2 row, and changing 2 3 Survey sheet, new row: do section section3 Add a sheet for section3 Usual columns: type, values_list, display.prompt.text New row, type: linked_table, values_list: select_linked_data, display.prompt.text: Household members Select_linked_data is the name you will use in your query, can change for different queries/subforms Add name column, leave blank Add display.new_instance_text column: Add member
27 Main survey: modifying queries In the queries sheet, add columns for: linked_form_id, linked_table_id, selection, selectionArgs, newRowInitialElementKeyToValueMap, openRowInitialElementKeyToValueMap New row query_name: select_linked_data query_type: linked_table linked_form_id: hh_member linked_table_id: hh_member selection: hhid = ? selectionArgs: [ data( hhid') ] newRowInitialElementKeyToValueMap: {hhid: data( hhid )} This says to create hhid in the sub-form openRowInitialElementKeyToValueMap: {}
28 Converting and testing Need to convert both the hh_member form and the firstForm form Test! Navigate to household id, enter 12345 Navigate along to household members Should be a + sign to add a new member This will take you to what looks like a survey/is the household member subform Should be able to answer questions for an individual, finalize subform, do another member, etc. Should see save date, name, and whether finalized Can edit, delete, add more members
29 Linking back again: question You can use the responses from a subform as values for a subsequent question Example: Name members of the household and pick one as head In firstForm section3, add a row, type: select_one, values_list: select_linked_data, name: head, display.prompt.text: Select the head
30 Convert and test Navigate to the members questions Add at least two members to the household Then click next Should have all the entered members as options for selecting the head
32 Purposes of preloading data It is possible to populate tablets with pre-existing data (preload data) Two main uses: Assigning instances to fieldworkers Can give an enumerator the info for the 20 households they are supposed to collect Preload some data, e.g. ids, locations Quality control Preload complete questionnaires collected by fieldworkers (5% sample) Review with households, making corrections
33 Preloading example Let s say we want to preload households on to fieldworkers tablets Let s assign some households to our tablet firstForm.csv in ODK Advanced Workbook Structure Solution d has: 11 household ids, a namelist , the other variables, and a set of internal tables variables Get these by filling out a blank form and downloading/exporting the data
34 New question Let s add the nameslist as a variable in section1 of firstForm Could add a lot more detail Insert a row before the current note: First Visit type: text, name: nameslist, display.prompt.text: Names
35 Convert and test The Tables functionality in preview is still under development, so we can t test preloading except on the tablet But we can check that our questionnaire generally works before pushing it to the tablet and testing
36 Location for preloaded data Preloaded data needs to be stored as a csv in assets/csv Then it will be imported with tables Copy firstForm.csv from ODK Advanced Workbook Structure Solution d to assets/csv
37 Push to tablet Attach the tablet Revisit the slides for pushing from app-designer to tablet Force stop: tables, survey, services Delete default folder in OI file manager Navigate to the app-designer directory within the command window grunt adbpush-default-app Hopefully done, without errors Open tables
38 Test in Survey Open Survey Should be able to see form and (on the tablet) subforms Let s run through a test observation Then check out the data in Tables Can see that the subform is stored in a different table (has a different table_id) Would need to link by hhid
39 Preloading our data In Tables, can import (and export) data On upper level, click on + to import, then select csv file to import Navigate to the assets/csv folder and select firstForm.csv Click pick file Click append to an existing table If all goes well, should say file import successful In tables, now can see the preloaded data
40 Working with preloaded data Now if you go to Survey and First Form, should see previously created instances with household ids from the table Let s pick one and edit Now can fill in rest of data, save, sync, etc.
42 Constraints Are specific to a variable. For example, we might want to constrain age to be 0-99 Show an error message and don t let you continue until you fix
43 Applying a constraint Let s constrain year of birth to be between 1900-2018 or 9998 for don t know Go to section2 and add a constraint column and a display.constraint_message.text column Constraint, q201 row: (data( q201 ) >= 1900 && data( q201 ) <= 2018) || data( q201 ) == 9998 Either (1) year of birth is greater than or equal to 1900 or (2) year of birth is 9998 for don t know Parentheses key for evaluating properly display.constraint_message.text, q201 row: Year of birth must be 1900-2018 or 9998 for don t know
44 Convert and test Can navigate in contents to try to start individual members Should be bounced back to hhid
45 e. Languages
46 Languages ODK supports multiple languages Can choose one as the default language Need to provide all display.prompt.text and display.title.text in both languages Will do with English as the default Non-defaults require .language, for example .arabic For simplicity, go back to the version of firstForm from the end of 08_ODK Creating and Testing a Survey in App- Designer Solution
47 Settings for languages Start on the settings sheet in firstForm Add columns display.title.text.arabic, display.locale.text.arabic, display.locale.text Add rows default and arabic display.title.text: display.locale.text, arabic row: Arabic, default row: English display.locale.text.arabic, arabic row: , English row:
48 Languages in survey/sections & choices Next we need to add display.prompt.text.arabic column to the survey sheet Let s just add content to this column for our test question in section 2 Also need to update choices sheet Add a display.text.arabic column Add to yes row Add to no row
49 Convert and test Now when you go to the survey and create a new instance, in the navigation button you should have language choices Choose Arabic Everything should now be labeled in Arabic Can make similar changes in framework, translating framework_translations tab with text.arabic