Difference in how once() function handles strings Vs numbers

I am building my first complex Kobo form using XLSForm definition.
I am learning a few things as I go. One thing I just learned is that when I use a calculated value as a default, ODK will recalculate the values upon finalization of the form, effectively overriding the user’s input.
The solution to this is to use once() function.

However, when I applied this solution, I immediately fell into this confusing trap. On one question, I have this calculation which is working well: once(if(substr(${national_id}, 5, 6) = '7', 'female', 'male'))

On the next question, this calculation doesn’t work at all: once(if(int(${age}) > 30, 'married', 'single'))
I am confused since when I remove once() from the second formula, it works as well.

I am trying to see the difference between the two and the only obvious one is that the first is comparing character strings and the second one is comparing numbers.

Any hints on how once() treats strings comparison vs numbers?

Hi @gashakamba sharing my quick thoughts which might be helpful to debug the situation.

First of all the behaviour of once() should be consistent regardless of whether it is dealing with strings or numbers. My suspicions are there might be some nuances in how expressions are evaluated that might be causing the issues you’re encountering.

Some potential issues could be:

  1. The data type conversions where in this case the int() function is mainly meant to convert string to integer. What if you remove the int() function what happens? Is the question type of integer type in the form?
  2. If the ${age} variable in this case has an initial value which is not an integer the calculation expression might not work in this case.

A proposed diagnosis for this could be:

  • make sure that ${age} is correctly defined with the integer question type since this is what you want
  • you can also use a debugging option like an intermediate calculate field to verify the value of ${age} before it is used in the once() function. This can help you understand if the value is being read correctly.

I hope this can be able to assist you. Regards

1 Like

Thank you @surveyorjr for the feedback.
I spent more than 8 hours diagnosing this issue; so I have a gone through all these suggestions to no avail.
In the end, I learned of another way of controlling when the calculation for my question happens. That solution is using the “trigger” attribute. I found this even more elegant solution that using once() which seemed a little bit hacky anyway.

2 Likes

What is the type of your variable age?
Is the int() function the right one here (truncating decimals)? See ODK XForms Specification.

Could you share a related extract of your form please, (in XLSForm format)?

Did you check your form with the Online validator? This is always recommended during development and before deployment.

@surveyorjr and @gashakamba,

Yes I checked my form with the online validator. I also tried my formula with number() instead of int(); same result. I also changed my “age” question type to “integer” to no avail. Looks like once() doesn’t wort with numbers at all.

For better support, we probably need this, please:

1 Like

I have made a simplified form definition in XLSform here. Here is a snapshot of the CSV file I am pulling data from.