Doubts about repeatable group instances

One aspect where A12 modeling does not make much sense to me is the handling of repeatable groups regarding the count of group instances.
Please help us out with some background info here, even though the text below is a bit lengthy.

In the docs it says

The Repeatability property sets the maximum amount of instances that are allowed to be created for the group.

Nice and easy to understand - or so it seems.

First doubt

When I tried to add a validation “There must be at least one item in your order” (items is a repeatable group), I naturally expected a function in the validation language like NumberOfGroupInstances(<group>).
All I found is NumberOfFilledGroups which is documented as

NumberOfFilledGroups determines the number of specified groups in a group list.

So a group is now a group list and instances (?) are “specified groups”?
What does “Specified” even mean? Oh wait,

A group is considered specified if it contains a specified field or subgroup.

Huh? Kinda recursive, isn’t it? (Reminds me of the classic Hacker’s Dictionary: “recursion: See recursion. See also tail recursion” :smiley: )
Oh, after reading some more docs it seems that “specified” is just another name for “filled” (Why two different words for the same thing? Is someone actively trying to confuse me?)

So, oookay, NumberOfFilledGroups kind of works for me here, because there are mandatory fields in the item group.
(So that when there is in fact an order item, but it is “unfilled”, then even though the “at least one order item”-validation would (erroneously) trigger, at least some real validation errors on the mandatory fields would show up).
Still feels like an ugly workaround.

Second doubt

On the “Item” group I have a computation like [TotalPrice] <- [Amount] * [UnitPrice]
I had in mind that in 2022.06 you no longer need to specify a precondition in a computation rule, if there is only one calculation.
When I tried that, I got a most peculiar error message

If the calculated field is repeatable, every partial calculation has to have values for its respective iteration".

Sorry, but from (my limited) modeler’s perspective that is gibberish.
I found some documentation that says

If the computed field is repeatable, the computation is carried out for each single repetition. In this case, the preconditions must assure that there is already some field value specified for the respective repetition layer.

This implies in particular: If the computed field is repeatable, then preconditions must be specified.

Note that, without such a restriction, even for an initially empty document the value 0 would be mapped into all 99 instances of TotalAmount.

Remarks:

  • The error message talks about how the “calculation has to have values”. Why is that any different in a non-repeatable group?
  • Couldn’t you change the error message to “If the computed field is repeatable, then preconditions must be specified.” - at least that would give me a hint what I actually have to do to fix the error.
  • WTH, srsly? Does that mean if I have a repeatability of 999, then the computation would check the preconditions 999 times even if there currently are only 2 instances of the group?

Yet another doubt

Do we maybe have this (to me) strange “Confirm” data type, just so that I can still use stuff like NumberOfFilledGroups?
With the more common Boolean data type, the group would be considered “filled” right?
The doc just says

A Confirm field is either true or not set (null).

but does not even mention why we would need a data type with these values (instead of the saner true/false)

Conclusion

It feels like some implementation decisions that were made long ago, have side effects that are leaking into the modelling experience.
Could somebody shed some light, please?

Hi @stephen-warm-graph ,

Here’s the way that I go about modelling repeats. Please note, I’m only going to comment on your questions regarding repeats in this thread. I will separate your question relating to Confirms and Booleans and put it in a separate thread.

Firstly, let me define my Document Model. In all examples in this answer, I will be working with a document model with the following structure:

  • Root (Group)
    • Order (Group, repeatability = 10)
      • UnitPrice (Field, Number, 2 decimal places)
      • Amount (Field, Number, 0 decimal places)
      • OrderComplete (Rule)
    • AtLeastOneOrder (Rule)

This answer relates to:

Counting the number of filled groups

Despite the concerns you mention regarding the documentation, I truly feel that it is your friend. There is a separate section in the documentation listing the “4.7.2 Functional language constructs for field lists and group lists”. This lists the language constructs that you can use for FieldLists and GroupLists and means that you do not have to guess the name of the language construct when writing a rule.

The language construct that you mentioned, NumberOfFilledGroups , is mentioned in this list, so it looks like a good candidate. You can easily write a rule the following rule:

NumberOfFilledGroups(Order*) < 1

This rule then checks if a group is specified. I agree that the documentation doesn’t shine much light on this issue. I found it very useful to use the Preview App Controller and consider what happens when an end-user trys to enter data. When the end user clicks on the add button in the repeat, the first order group is specified. You can see this when using the developer tools in your web-browser (F12) and selecting “Network Analysis” and then the tab “Reply”. If you save your form and then look at the last entry, you can see what you are saving. By clicking on “Add” in a repeat, you create an empty Object in your repeatable group. In other words, you specify a group. If there is no mandatory field in the group, then you can save the form as you have specified a group. The fields, which do not contain any data are not specified.

The workaround that you suggest, making at least one of the fields mandatory, however not ensure that all the fields in each line of the order are filled. As modeling multiple rules allows you create very specific error messages for the user, we would always recommend modeling two rules.

One rule that ensures that a group has been specified, AtLeastOneOrder (Rule) in my Document Model:

NumberOfFilledGroups(Order*) < 1

Error Message: “Please add at least one item to your order”

And another rule that checks if the row if completed, OrderComplete (Rule) in my Document Model:

GroupFilled(RuleGroup) and
NotAllFieldsFilled(UnitPrice,Amount)

Error Message: “Please complete all the fields in this row of your order”

This second rule check that each time the user clicks on “Add” in the detached repeat, and therefore specifies a group, that the listed fields are filled.

Hi @stephen-warm-graph,

This answer relates to:

Calculation with repeats

Firstly, let me define my Document Model. In all examples in this answer, I will be working with a document model with the following structure:

  • Root (Group)
    • Order (Group, repeatability = 10)
      • UnitPrice (Field, Number, 2 decimal places)
      • Amount (Field, Number, 0 decimal places)
      • OrderComplete (Rule)
      • TotalPrice (Field, Number, 2 decimal places)
      • TotalPriceComputation (Rule)
    • GrandTotalPrice (Field, Number, 2 decimal places)
    • GrandTotalPriceComputation (Rule)
    • AtLeastOneOrder (Rule)

As you can see, I’ve added two calculations to my Document Model, one to calculate the total price in each row of the repeat, TotalPriceComputation, and another to calculate the price of the whole order, GrandTotalPriceComputation.

It is not clear to me how you have modeled the computation in your Document Model. I can only tell you that for TotalPriceComputation, you need a precondition and for GrandTotalPriceComputation you do not. I modeled the computations as follows:

TotalPriceComputation

  • Precondition
GroupFilled(RuleGroup)
  • Computation
RoundAccounting([Amount]*[UnitPrice],2)

GrandTotalPriceComputation

  • Precondition

  • Computation
RoundAccounting(SumOfProducts(Order*/Amount,Order*/UnitPrice),2)

Please note, you need to use one of the language constructs for rounding when working with decimal places.

As you can see, the first rule has a simple precondition to check that a group has been specified before running the calculation. In other words, has the user click on the “Add” button on the repeat? If not, then do not run the calculation. The second rule has no precondition and will return 0,00€ if the Order is empty.

To demonstrate the function of NumberOfFilledGroups you can try using this in a Computation Rule.

If you model a Computation Rule as follows:

  • Precondition

  • Calculation
NumberOfFilledGroups(Order*)

In the application or in UI Designer Preview, you can see that each time you click on “Add” the NumberOfFilledGroups increases by one. This is independent of whether the fields in the row are completed or not. If you use the UI Designer to add initial rows to the repeat, you will also see that the NumberOfFilledGroups is equal to the number of initial rows when you start the application or the UI Designer Preview.