Conditional relevant Geopoint omits calculate value

We’ve found that it’s not possible to conditionally set the “read only” property of the Geo widget, or perhaps any widget.

As a result we wrapped our geo widget, and accompanying geo related questions, in a group with a relevancy check.
Unfortunately it seems that doing so causes the geopoint widget to no longer grab the previously saved value.

Our use case is after a plot’s location has been verified by an admin/site manager, the location should no longer be editable by a CHW.
However, should the admin/site manager clear the verification status, the previously saved location should re-populate the geopoint widget.
Could you perhaps suggest a workaround to satisfy our requirement?

Please see the create and edit forms.

Screenshot for reference:

Steps to recreate:

  1. Create the plot with a location
  2. Edit the plot setting the “Has the location been verified” to true.
  3. Edit the plot again and set the “Has the location been verified” to false. Note the location value not pulling through.

Hi @Anro - thanks for your question!

It sounds like there’s two issues you’re facing maybe - can you clarify?

  1. I think ideally you would have the geopoint input required? Maybe it is covered in this yet-to-be-solved ticket, " Add a native GPS field that can be required in the UI #6657 "?
  2. As a work around to not being able to make the form required, you have made the geopoint input conditionally show based on the location_verified field’s in dwelling-edit form, but you find when this geopoint is hidden an shown the value for geopoint is lost?

As well, could you specify which version of CHT Core you’re server is on and, if applicable, which version of CHT Android?

Finally, note that when available, all forms should include geolocaiton_log and geolocation data as seen in this example JSON. Final improvements to this feature were made in 3.10.0, so you likely have it already!

Hi @mrjones

Thank you for your detailed response.

  1. In our case, and perhaps fortunately, we don’t want to the geopoint input as required. This is because some of our devices have broken GPS modules OR our CHWs face environmental factors such as safety concerns.

  2. but you find when this geopoint is hidden an shown the value for geopoint is lost? That is indeed the case. However, our reason for hiding and displaying the question based on the location_verified is because our “site manager” needs to “lock in” the location once they’ve verified that it is indeed at the correct spot. Prohibiting the CHW from changing it again. Location can be captured accurately (sub 5m), but not necessarily at the correct position. Especially when considering densely populated areas. So this is to safeguard our data once confirmed, which will then be put on a stakeholder map by one of our downstream processes.

Our server is currently on CHT Core version v1.8.6 (~4.3.2). As per the about screen.

That would only be for app forms correct? We’ve not seen GPS collected for our hierarchy forms.
In our case we need the GPS collected on a PLACE create/edit form.

Okay, so I have a couple theories here that I want to present in order of increased complexity (once again, very helpful to have the actual forms to dig into!):

Theory #1

I wonder if you are just getting burned by the circular dependency between init/loc/location and PLACE_TYPE/location. Basically, when the edit form loads, the value of PLACE_TYPE/location ends up getting cleared because it tries to evaluate init/loc/location which does not yet have a value. Can you try adding a coalesce to the calculation of PLACE_TYPE/location to always fall back to the existing location? coalesce(../../init/loc/location, .)

Theory #2

What CHT version are you trying this on? Weird behavior around existing data in non-relevant fields existed from 4.0 to 4.5. If you are in that range of versions, it would be worth testing against 4.6+ to see if you can still reproduce the problem.

Theory #3

This is related to #2, but is much more speculative around some unknown bug in the confluence of the geo-widget, edit contact forms, and non-relevant fields. Non-relevant fields don’t behave quite the same when being saved in a contact edit form (instead of clearing the field value, it just stays its original value if it becomes non-relevant in the edit form). Once again, it would be good to know your CHT version here to see if we can repro this behavior.

1 Like

Fantastic! Thank you so much for taking the time time write detailed feedback, and apologies for my delayed response.

Theory #1
Please don’t say that too loudly, we use that in quite a few places :sweat_smile:. Usually we don’t refer to the “save block” value directly, but rather that prev_some_value intermediary variable as seen in the form. In most cases that solved our problem. Perhaps as you noted in point #2, it’s because of our version.
That being said, I’ve implemented the coalesce as suggested and it seemed to have populated the GPS input fields, but unfortunately does not update the map.
image

Theory #2
We’re on version 4.3 at the moment :smiling_face_with_tear:. We’re still a ways off from 4.6 unfortunately, although we’ve put in quite a bit of work to detach ourselves from our grunt tie-ins, so hopefully it’ll be quicker iterations once stable on 4.4. Hopefully very soon.

Speaking of, and while it’s a veering a bit off topic, has the draw/signature widget implementation been backported to 4.6 where enketo introduced the “canvas clearing” issue? It may result in us needing to take larger upgrade leaps.

Theory #3
I’m hoping the above feedback provides some sort of clarity regarding that concern.

Just wanted to follow up here and say that I finally got some time to tinker with this, but I have not been able to reproduce this behavior on 4.3 (or on the latest in master) even when using the linked contact forms. When editing the contact, I always see the map populated and zoomed in (though, there does seem to be a rendering issue where the map is off center when the widget is on the first page of the form). Putting the map on a subsequent page or resizing the browser window seems to recenter the map. Do you happen to see something like this when editing the contact? (Note that most of the map is greyed out)

But, when I resize the window, even slightly, it renders correctly:

This behavior happens for me in both 4.3 and latest, but I have a theory that the rendering issue is related to similar behavior I observed for the draw widget.


We do not generally patch features back to previous major/minor versions (like we do for bug fixes, etc) so there is no plan to backport that code to 4.6. I would say that if you end up being too cautious with your upgrade leaps, you will probably have trouble keeping pace in the long-term. However, the CHT code base is far from being “high-churn”, so I imagine a 4.3 > 4.9 jump is not unreasonable. The important thing to note is that the draw widget code included in 4.9 is basically the same as what you have now in your fork of 4.3. No version of the CHT ever included the subsequently reverted “new/broken” draw widget code that was briefly included in the Enekto code-base. But, yes, if you go to 4.6 - 4.8, you will not want to depend directly on the version of the draw widget from enketo-core since that is the bugged code. Back patching just the widget code from 8904 should get you widget functionality that is equivalent to what you have now.

One final thing to note is that in the future, once we have uplifted to the latest enekto-core we want to remove the draw widget back out of cht-core and just depend on the one in enekto-core. However, before that happens, we are trying to implement an upstream fix for some issues we identified…

1 Like

I’m not sure what I did to achieve that behavior, but I’m unable to recreate it at the moment :face_with_raised_eyebrow:. I’ll play around with it a bit more.
As for the map loading off-center and mostly grey, I’ve definitely been seeing that on my side as well.
image
Zooming in and out seems to have no affect.
image
Like you said, as soon as the window resizes, everything gets rendered correctly.

That is very interesting, and good to note. We’ve never run into that problem because all our signatures are on the second or later pages.
Why does the _resizeCanvas function not trigger as soon as the loader gets hidden on initial load?

Thank you for explaining our options in such a detailed fashion, I think we’re going to go with your first suggestion of leaping to 4.9. Before we can do that we’re just making sure the upgrade were busy with 4.4, which includes us reworking our tied in grunt tasks, is on a stable footing.
That way we’ll be in step and miss those “never lucky” threads we’ve had in the past :smile: (I’m looking at you app form that can be hidden in care guide but then breaks scheduled tasks until v4.3).
While we are on the topic of the upgrades, 4.4 also includes the CouchDB 2.x to 3.x upgrade. A colleague of mine is looking into that, but are you aware of any pitfalls we might need to watch out for? Or is it a non-concern?

Duly noted, it keeps things clean. Similar to how we try to approach our project patch folder. Based on the information in that thread, it seems like Enketo themselves have had a tough time with things revolving around the draw widget. This will be no small feat.

1 Like

As for the map loading off-center and mostly grey, I’ve definitely been seeing that on my side as well.

Thanks for confirming this. At least we are observing consistent behavior! :sweat_smile: I have logged an issue for this: Geopoint Widget map rendering issue when on first page of the form · Issue #9268 · medic/cht-core · GitHub

Why does the _resizeCanvas function not trigger as soon as the loader gets hidden on initial load?

I have not had the time to dig into the geopoint code yet to confirm any of this, but for the draw widget, the canvas resize logic was not actually directly tied to the visibility of the widget (e.g. the css display value), but instead was triggered either by form state changes (relevant expressions or page turns) or directly by the window resize event. In the CHT, we show a loading spinner while the form is loading. What this means, though, is that during the initialization of the widgets, they are not actually taking up any space on the page. This is what was throwing off the draw widget logic. Then, when we do finally display the first page of the form, nothing happened that would actually re-trigger the _resizeCanvas.

are you aware of any pitfalls we might need to watch out for? Or is it a non-concern?

We did learn the hard way that just because you are using Couch 3, does not mean you can immediately start using ES5 JS code in the Couch views. This is because when staging an upgrade, the new views get warmed by the old version of Couch before the new instance is started. So, if you are upgrading from CHT <= 4.3, all of your new Couch views need to be compatible with Couch 2.x. This should not be an issue for you if you do not have any custom view code (and you are upgrading to the latest patch release for whatever minor you are targeting). Besides that, the only difference you should notice when running Couch 3 is a nice performance boost in multi-CPU environments!

1 Like

Still at a loss as to why I can’t re-create the previous behavior, but it’s bitter-sweet that we’re at least able to confirm this one for you :sweat_smile:.
Thank you for opening the issue!

Ahh I see. So your thinking is most widgets would follow the same type of approach when it comes to these rendering triggers. Do you believe if one made a “visibility” change callback available to implementers that it could be used to circumvent the current issue? Even if that’s the case, one would probably be apprehensive to do so as it becomes an area of continued maintenance.

That is a VERY welcome heads-up, thank you :eyes:. I’ve forwarded this piece of info on to my colleague that’s currently busy with our upgrade planning :smiley: !
We’ve not written any custom views, yet, but have started looking into it - specifically to see if we can neatly link a family unit (parents and their biological children).
Came across some forum threads that mentioned views going missing due to re-using view files that gets replaced during upgrades. If we go down that route, we should rather create our own view files.
Can always do with a nice performance boost :grin:, especially since we’d like to reduce the time our couchDB-connector takes to pull records into our processing space.

Thank you again for all the info!

1 Like

Yeah, so digging into the widget code a bit, it looks like the leaflet map.invalidateSize() function call is what is going to properly redraw the map canvas. It gets called here in the widget enable function. But, in the CHT, the widgets are “enabled” while the loading indicator is still displayed (so the canvas will not have any size). Looking at the other places where the widget calls map.invalidateSize(), it is clear it gets called when the page turns. This matches the behavior we have seen where the map is correctly rendered on subsequent pages. Also, in the leaflet Map.js code, it looks like the invalideSize() function is connected to the window resize event which explains why resizing the window fixes things too.

Exposing some kind of callback from the widget that the CHT could call to trigger map.invalidateSize() would be a possible solution, but then that would require additional code in the CHT to make sure the trigger is called once the form is actually displayed. An alternative approach might be to leverage a ResizeObserver in the actual widget code similar to what I am proposing in my draw widget PR. That may be able to handle the existing cases (e.g. page turns, etc) while also making things work find for consumers like cht-core… :person_shrugging:

1 Like