Referencing the Location/Organization Hierarchy in Applications

Please note the documentation below requires more technical expertise

The documentation below may require knowledge of more technical software management and development topics.

This page discusses how to reference the location hierarchy in various parts of apps.

Enabling Access to Location Hierarchy

All new projects have the location hierarchy.  

Some older projects may be setup to only receive the Old Hierarchical Fixture.  To transition to the flat fixture, go to project settings, then choose Pre-Release Features -> Location Fixture.  You can use this to turn on the new location format (flat fixture).  Once you have done this, new versions of the app will start to use the new location format.  Once all your existing users have transitioned to a new version of the application that uses the new location format, turn off the hierachical fixture.  This process is described in depth at https://dimagi.atlassian.net/wiki/x/cinKfw.

The User's location

To pull the current user's location ID you can use the "commcare_location_id" session variable. To reference this in a form, use the following expression: 

 instance('commcaresession')/session/user/data/commcare_location_id

The Location Hierarchy

To reference the location hierarchy in forms you need edit the source XML by hand and construct complicated xpath expressions. 

Ensure that the Locations Data Source is Available

First, you'll need to make sure that the form has a reference to the Locations data source.

The easiest way to accomplish this is to ensure that your question has at least one select question with locations as choices.

If your form doesn't contain one of those questions you can create a 'dummy' question:

  • Below you'll see instructions for "Making select questions with locations as choices"

  • Follow those instructions to add a locations lookup to the form

  • Set the Display Condition for that question to false()

After those steps you should be able to reference locations elsewhere in the form.

Note: If you are using a Locations driven select question in the form, you won't need to keep around the 'dummy' question as well.

Referencing the properties of the user's location (or location ancestor) in a form

 You can use the following templates to reference the properties of the user's location (or ancestors). These examples assume a hierarchy of state --> district --> block --> outlet. These expressions will need to be customized to your own hierarchy.  To find the code to use for each organization level, on the Organization Level page, click on the Advanced checkbox.  

For example, if my location hierarchy has village →  city → county→ and I'm trying to pull the city's ID for my current village user, I would take this example from below: 

instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/@block_id

and modify @block_id to say @city_id  

 instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/@city_id

I am a...

referencing my...

syntax in forms

outlet

own location's name

 instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/name

outlet

own location's type

 instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/@type

outlet

own location's site code

 instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/site_code

outlet

own location's custom data

 instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/location_data/custom_field_id

outlet

parent block's id

 instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/@block_id

outlet

parent block's name

instance('locations')/locations/location[@id =  instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/@block_id]/name

outlet

parent block's name

instance('locations')/locations/location[@id =  instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/@block_id]/site_code

outlet

parent district's id

instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/@district_id

outlet

parent district's name

instance('locations')/locations/location[@id =  instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/@district_id]/name

block

parent district's id

instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/@district_id

block

parent district's name

instance('locations')/locations/location[@id =  instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/@district_id]/name

district

parent state's id

instance('locations')/locations/location[@id = instance('commcaresession')/session/user/data/commcare_location_id]/@state_id

Accessing the location additional information (Location Fields)

Once you have the location's ID you can access it to get other information.

These examples assume your ID is stored in a hidden value called location_id

Referencing...

syntax in forms

Referencing...

syntax in forms

The gps of the location

instance('locations')/locations/location[@id = /data/location_id]/latitude

instance('locations')/locations/location[@id = /data/location_id]/longitude

Any custom location fields you may have (ex. admin name)

instance('locations')/locations/location[@id = /data/location_id]/location_data/admin_name

Making select questions with locations as choices

You can use the location hierarchy to make select questions that allow you to choose a location in a form. The process is similar to setting up multiple choice questions with cases as choices.

  1. Go to Application Settings to turn on the Custom Single and Multiple Answer Add-On in the "Calculations" section.

  2. Add a new "multiple choice lookup table" question

  3. In the "lookup table data" choose the 3 dots next to the list of lookup tables

  4. Set the query to: instance('locations')/locations/location[@type = 'TYPE OF LOCATION']  NOTE:  "type of location" is given for each organization level by the "type code." You can see the type code when you click on "Advanced Mode" on the Organization Levels page. 

  5. Set the instance ID to locations

  6. Set the instance URI to jr://fixture/locations

  7. Hit save

  8. Set the value to "@id" and the label to "name"

Tiered Location Selection

You can also add tiered selection (e.g. select state, then district, then block) by adding multiple select questions after each other as described above.  Assuming the example of districts and block:

  1. Setup the district list as described above  (this example assumes the question_id is district)

  2. Add a second multiple choice question, and configure it to display a list of blocks

    1. In the filter section, add a filter with the following: @district_id = /data/district 

Example location fixture structure

Example locations fixture
<fixture id="locations" indexed="true" user_id="b43e50ca1c3174fe0bbcf36cfd93a1eb"> <locations> <location id="999dc78d9ca84ea8749dc75b44542332" type="country" country_id="999dc78d9ca84ea8749dc75b44542332" state_id="" county_id="" city_id=""> <name>USA</name> <site_code>usa</site_code> <external_id/> <latitude/> <longitude/> <location_type>country</location_type> <supply_point_id/> <location_data> <name-en>USA</name-en> <name-es>USA</name-es> <is_test/> </location_data> </location> <location id="999dc78d9ca84ea8749dc75b44541bdc" type="state" country_id="999dc78d9ca84ea8749dc75b44542332" state_id="999dc78d9ca84ea8749dc75b44541bdc" county_id="" city_id=""> <name>Massachusetts</name> <site_code>massachusetts</site_code> <external_id/> <latitude/> <longitude/> <location_type>state</location_type> <supply_point_id/> <location_data> <is_test/> </location_data> </location> <location id="999dc78d9ca84ea8749dc75b44540257" type="county" country_id="999dc78d9ca84ea8749dc75b44542332" state_id="999dc78d9ca84ea8749dc75b44541bdc" county_id="999dc78d9ca84ea8749dc75b44540257" city_id=""> <name>Middlesex</name> <site_code>middlesex</site_code> <external_id/> <latitude/> <longitude/> <location_type>county</location_type> <supply_point_id/> <location_data> <name-en>Middlesex</name-en> <name-es>Middlesex</name-es> <is_test/> </location_data> </location> <location id="999dc78d9ca84ea8749dc75b4453ff5b" type="city" country_id="999dc78d9ca84ea8749dc75b44542332" state_id="999dc78d9ca84ea8749dc75b44541bdc" county_id="999dc78d9ca84ea8749dc75b44540257" city_id="999dc78d9ca84ea8749dc75b4453ff5b"> <name>Cambridge</name> <site_code>cambridge</site_code> <external_id/> <latitude/> <longitude/> <location_type>city</location_type> <supply_point_id/> <location_data> <is_test/> </location_data> </location> </locations> </fixture>

Syncing more of location hierarchy to users

By default, CommCare will only send each user the list of their assigned locations and those location's ancestors and descendants.  For example, if I'm assigned to a block,  I will get a list of my state, my district, my block and all that blocks outlets.  

In some situations, you may want to get a list of locations outside of the ancestors and descendants.  In the example above, if a user is assigned to a block, they may want to see all districts in that state anyway. This is controlled using the "Expand From" options outlined on https://dimagi.atlassian.net/wiki/x/GW-Kfw.