Variable for csv filename in pull-data

Hi @nancyv, @wroos, this is related to the discussion here about trying to include images dynamically.

Unfortunately, Enketo resolves the URLs (jr://...) on the backend and fetches the external data when the form is first loaded — therefore it needs to know the filename upfront. You can see this difference in the XML of the XLSForm, one with a dynamic filename and one fixed (example from the XLSForm docs on pulldata):

survey 1

type name label calculation
calculate filename ‘fruits’
calculate fruit pulldata(${filename}, ‘name’, ‘name_key’, ‘mango’)
note note_country The fruit ${fruit} is pulled csv data.

survey 2

type name label calculation
calculate fruit pulldata(‘fruits’, ‘name’, ‘name_key’, ‘mango’)
note note_country The fruit ${fruit} is pulled csv data.
@@ -14,10 +14,10 @@
           </meta>
         </aUJ4gsohDFa8wmxGiSs5Dg>
       </instance>
-      <instance id="${filename}" src="jr://file-csv/${filename}.csv"/>
+      <instance id="fruits" src="jr://file-csv/fruits.csv"/>
       <bind calculate="'fruits'" nodeset="/aUJ4gsohDFa8wmxGiSs5Dg/filename" type="string"/>
       <bind nodeset="/aUJ4gsohDFa8wmxGiSs5Dg/n" readonly="true()" type="string"/>
-      <bind calculate="pulldata( /aUJ4gsohDFa8wmxGiSs5Dg/filename , 'name', 'name_key', 'mango')" nodeset="/aUJ4gsohDFa8wmxGiSs5Dg/fruit" type="string"/>
+      <bind calculate="pulldata('fruits', 'name', 'name_key', 'mango')" nodeset="/aUJ4gsohDFa8wmxGiSs5Dg/fruit" type="string"/>
       <bind nodeset="/aUJ4gsohDFa8wmxGiSs5Dg/note_country" readonly="true()" type="string"/>
       <bind jr:preload="uid" nodeset="/aUJ4gsohDFa8wmxGiSs5Dg/meta/instanceID" readonly="true()" type="string"/>
     </model>

In the network tab of your browser’s dev tools, you can see that the form with a dynamic filename does not make a GET request for the data, but when the filename is declared upfront you can see:

Additionally, you can see the difference in how Enketo resolves these URLs in the response to the POST request made to /transform/xform:

@@ -14,5 +14,5 @@
             </meta>
         </aUJ4gsohDFa8wmxGiSs5Dg>
     </instance>
-    <instance id="${filename}" src="jr://file-csv/${filename}.csv"/>
+    <instance id="fruits" src="/media/get/https/kc.kobotoolbox.org/joshuaberetta/xformsMedia/970740/1564798.csv"/>
 </model>

So in summary, you will have to do something similar to what I recommended in the linked thread where you load all external data and then reference it inside the form in a dynamic way. Hope that helps :slightly_smiling_face:

2 Likes