Thanks for this proposal, @martijnr! It would indeed be great to add to XLSForm.
What are you imagining that the resulting XML would look like? Would the calculate
become a field with a string
bind
, no calculate
and no corresponding body
control element? It seems that it can't have a calculation or that would override the result of any setvalue
action, right?
That was also my gut reaction and it's still making me uneasy.
It's not really the case that a field is a trigger for a setvalue
, the trigger is the change in that field. If you're comfortable with a field being in the proposed trigger
column, how about using the label when
? I think that works very nicely for other events
type |
name |
label |
calculation |
when |
text |
a |
Enter text |
|
|
calculate |
b |
|
now() |
${a} |
I think the two major use cases for the value changed event will be to pull some value from outside the form as you've demonstrated (time, location) and setting dynamic defaults based on values supplied by the user (typically pulled from external datasets).
Do you agree that the latter case is worth supporting? In that case, trigger
would need to apply to types other than calculate
.
When I started thinking about this, I was imagining it flipped so that the expression would be defined in the row of the value that changes. For example, to set the value of b when a changes, I was thinking of something like:
type |
name |
label |
on_change |
text |
a |
Enter text |
${b}=instance('foo')/root/item[name=${a}] |
select_one foo |
b |
Select one |
|
(Note that this would probably be more realistic with pulldata
given current documentation)
The downsides of this is that it introduces some new syntax with the =
and that it's not as clear what the hidden value case like your example should look like. One concept would be to introduce a column for suppressing a body element:
type |
name |
label |
on_change |
user_facing |
text |
a |
Enter text |
${b}=now() |
|
dateTime |
b |
|
|
no |
This would also address the request for typed calculate
fields that comes up periodically. I think that pyxform
could validate that a field without a body element is either the target of an action or has a calculation but not both. But this adds to the cross product of possible question properties so certainly adds complexity.
One of the things you mention thinking ahead to is how to surface the setgeopoint
action triggered by events other than odk-instance-first-load
which I agree is important. Is this what you'd have in mind?
type |
name |
label |
trigger |
text |
a |
Enter text |
|
auto_geopoint |
b |
|
${a} |
In what I described as an alternative, this might be done by introducing a special keyword that could be used in the default
or on_change
columns. That wouldn't feel so clean.
I'm still thinking through all this and am not advocating for one solution over the other yet. I hope that sharing my thinking may spark some ideas.