Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#45 repeat-groups are not respecting the jr:count setting after a change to a lower value #61

Closed
wants to merge 3 commits into from

Conversation

mdudzinski
Copy link
Contributor

Fixes #45.

I hope commits messages, code and comments are comprehensive but here goes a short summary.

The code responsible for actual deletion of the extraneous repeats is simple:

   do {
     getForm().deleteRepeat(index);
   } while (getForm().getMainInstance().resolveReference(index.getReference()) != null);

but after the deletion, index points to the non-existing repeat group which leads to an error shown on UI (ODK Collect) . To fix this, the index must be incremented after the deletion and before it's assigned to currentFormIndex. This leads to another problem - a non-relevant (hidden) form element may be present right after the deleted repeat group. Skipping over such indices takes place before updating the model so it must be repeated. It's achieved by checking the current index after jumpToIndex(index) and recursively calling stepEvent(forward) if needed.

Michal Dudzinski added 3 commits June 5, 2017 18:33
The problem description:
Repeat groups that are controlled by the jr:count attribute which is
a path to a node (a number question) that holds the actual value
do not respect situation where the value is *decreased*.

Example:
User starts a form and puts 6 as the answer for the question that
controls the jr:count of the repeat group.
As (s)he is going forward, the repeat groups are properly created
by FormEntryModel.
The user goes back to the number question and changes it to 3.
As (s)he is going forward, the new value is ignored
by FormEntryModel and the number of repeat groups is still 6.

Solution:
The most of the magic takes place in
FormEntryModel#createModelIfNecessary(FormIndex) method which takes care
of creating the missing repeat groups by comparing the count value with
the currently being processed group instance index. If the index is
lower than the count value and the group does not exist, the method
creates it.
Now the method also checks if the instance index is *higher* than the
count value. If so, it deletes the currently processed group and all
the following (if any) in a loop.
If there is at least one repeat group to be deleted
during updating a model, user will be taken to the first form index
after the deleted repeat group(s). This happens after FormEntryController
already skipped non-relevant indices so the skip must be repeated if
the the first index after the deleted repeat group(s) is non-relevant
(hidden).
* Changed FormEntryModel#createModelIfNecessary to
  FormEntryModel#updateModelIfNecessary. Now this methods creates
  and removes repeat groups so the new name makes more sense to me.
* Changed FormEntryModel#updateModelIfNecessary body so it now uses
  Guard Clauses instead of Nested Conditions. The execution path should
  be cleaner now.
@mdudzinski mdudzinski changed the title #45 #45 repeat-groups are not respecting the jr:count setting after a change to a lower value Jun 6, 2017
@lognaturel
Copy link
Member

Thank you @mdudzinski! Will try to review soon. I want to make sure I get a chance to think through implications.

In the mean time, other comments and reviews are welcome!

@lognaturel
Copy link
Member

@mdudzinski This has not been forgotten, I promise. As you have seen on the forum, there are a lot of exciting things happening all at once in the ODK community. I want to make sure we are thoughtful in assessing the impact of this change.

@mdudzinski
Copy link
Contributor Author

@lognaturel no worries, I understand. This is being tested on our side so we'll let you know the results here. In the meantime, I'll appreciate any technical input because I still have a feeling that I missed something in the implementation:)

@mdudzinski
Copy link
Contributor Author

mdudzinski commented Sep 19, 2017

@lognaturel Just to let you know that this change has been released with the latest TaroWorks version. It's been working fine so far but TaroWorks uses only a subset of Collect/JavaRosa XForm capabilities and therefore it would be nice to have another pair of eyes to look at this.

I'll hold on with fixing the conflict till it's decided whether this approach is really wanted.

@lognaturel
Copy link
Member

Thank you for that update, @mdudzinski!

Did you end up including some kind of notification or confirmation for the user? Since this is a change in existing behavior, I have mild concerns about data loss. It should probably be clear to a user when they change the value that they could be losing records.

@mdudzinski
Copy link
Contributor Author

mdudzinski commented Sep 26, 2017

@lognaturel Nope. TW didn't have a requirement to inform the users about potential data loss. But I can imagine that some Collect's could be surprised.
That's something to be implemented on the client side. But since a field that is referenced by jr:count doesn't actually know it's referenced - it's not easy. The other challenge is creating or deleting repeat groups "in place". This means it happens where a user actually tries to go to the repeat group that is supposed to be created or deleted. So nothing happens if the user changes the value to a lower one, go somewhere (but not to the repeat group's instances that will be deleted:)) and go back and change the value to the original one. Perhaps JavaRosa should incorporate a some kind of observer pattern (RxJava?) so it could emit messages about things that's going to happen. Client apps could then respond to those messages. For example by displaying a pop-up informing about potential data loss. Just a rough idea.

@getodk-bot
Copy link
Member

Heads up @mdudzinski, we just merged some commits that conflict with the changes your made in this pull request! You can review this repository's recent commits to see where the conflicts occur. Please rebase your feature branch against the upstream/master branch and resolve your pull request's merge conflicts accordingly.

@grzesiek2010
Copy link
Member

grzesiek2010 commented Nov 20, 2017

@mdudzinski
I have got this form:
repeatTest.xml.txt

it contains:

  1. Select one Question (Yes/No)
  2. Numeric Question (visible only if you selected yes)
  3. Repeat group where the count of this group depends on the second question.

If I select yes then I pass 3 for example I can see 3 groups. ✅
If I go back and change 3 to 2 I can see two groups. ✅
If I go back and select no instead of yes the second question is not visible but I stiill can see all repeat groups. 🐛

The workeround here is to add:

to the repeat group as well.

My question is: isn't it something you should/could fix as a part of this pr too?

@mdudzinski
Copy link
Contributor Author

@grzesiek2010 Hmm this is a quite different scenario. When createModelIfNecessary looks for the count value it gets null. If null, then method returns and no new group is added (in the existing code) and no group is deleted (in the code from this PR). It's technically possible to delete all repeats if this happens but I think it should be discussed. I believe @lognaturel has a lot of concerns about the data loss possibility.

@lognaturel
Copy link
Member

Agreed that is pretty different although it's true that the effect feels similar to users.

@mdudzinski is right that I'm concerned about accidental data loss. That's why this PR hasn't been merged -- the behavior has previously been considered a feature not a bug. Search for "repeat-groups are not respecting the jr:count setting after a change" on the page https://opendatakit.org/help/form-design/workarounds/. You'll see that the recommendation is to use relevance to hide any extra values. This works really well and means that if someone had entered 10, wanted to change the value to 12 but accidentally entered 2 they wouldn't lose a bunch of records.

@lognaturel
Copy link
Member

This continues to be considered intended behavior.

@lognaturel lognaturel closed this Jun 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

repeat-groups are not respecting the jr:count setting after a change to a lower value
4 participants