Problem with refreshing value of a variable

Hi,

I got a form with an editable grid layout. on each row it can be added an amount. This is populated by a Rule input that contains :

  • FeuilleFrais -> CDT
  • FeuilleFrais.montantTotal -> total amount.
  • FeuilleFrais.listeFrais -> list of another CDT
  • FeuilleFrais.listeFrais.montantConverti -> the amount for the row.

I have a local variable that store the total amount and which is updated each time that one field montantConverti is updated :

  local!total : 
  a!refreshVariable(
    value:    if(
      isnull(ri!FeuilleFrais.listeFrais),
      0,
      if(
        sum(ri!FeuilleFrais.listeFrais.montantConverti)>0,
        sum(ri!FeuilleFrais.listeFrais.montantConverti),
        0)
    ),
    refreshOnReferencedVarChange: true,
  ),

This part is working fine.

Now I try to update the value of local!total into ri!FeuilleFrais.montantTotal.

This working fine when I submit the form, I got the right value into ri!FeuilleFrais.montantTotal. Now comes my issue, I do have a button to do some conversion and basically update the value of all the fields FeuilleFrais.listeFrais.montantConverti. As FeuilleFrais.listeFrais.montantConverti has been modified local!total is then also modified. This is working fine.

But even if I add : a!save(ri!FeuilleFrais.montantTotal, local!total) afterwards in my save into section the value of ri!FeuilleFrais.montantTotal is not updated with the current value of local!total but with the previous one.

If instead of local!total i add the complete code in the a!save function then ri!FeuilleFrais.montantTotal is correctly upated.

I guess that my issue is due to some variable refresh issue but I can not see where. for now as a workaround I have to replace local!total by all the logic to compute it.

Any idea on what I m doing wrong ?

Thanks for your help.

Nicolas

  Discussion posts and replies are publicly visible

Parents
  • Hi Nicolas,

    I'm not sure I totally understand the set up of your expression, but I think I may know what is happening. Basically, variables refresh *after* all saves are completed - this is how SAIL works. So in your case, you would need to put the logic to update local!otal in our saveInto before you do a!save(ri!FeuilleFrais.montantTotal, local!total) since local!total will refresh after the save have been completed. I plan to add an example of this to the documentation shortly. Here is a preview of that:

    When a component's value is updated and its saveInto parameter is evaluated, all saves inside of the saveInto parameter are evaluated before any local variables are refreshed. This means that saving into a local variable and attempting to use another local variable which depends on the first local variable's value later in the saveInto will still use the original value of the second local variable.

    Let's look at an example to which illustrates this behavior.

    a!localVariables(
      local!number,
      local!greaterThanFive: tointeger(local!number) > 5,
      local!message,
      {
        a!integerField(
          label: "Enter number",
          instructions: local!message,
          value: local!number,
          saveInto: {
            local!number,
            a!save(
              target: local!message,
              value: if(
                local!greaterThanFive,
                "This number is greater than five",
                "This number is less than or equal to five"
              )
            )
          }
        )
      }
    )

    In this example, I have 3 variables: local!number, local!greaterThanFive , and local!message.

    • local!number is used to hold the value of the number entered in the integer field.
    • local!greaterThanFive checks if local!number is greater than 5. This value will automatically refresh when its dependent, local!number, is updated.
    • local!message will hold a message after entering a number.

    Typing a number into the integer field will trigger the saveInto of the integer field to be evaluated. First, the value entered is saved into local!number. Then, a message is saved into local!message. In this a!save(), the value is determined by an if statement which uses local!greaterThanFive to check if our value is greater than five and returns the corresponding message to be displayed in the instructions.

    However, if we test this out by typing in the number 7, we see that the message returned is "This number is less than or equal to five" instead of "This number is greater than five".

    The incorrect message is returned because local!greaterThanFive does not refresh until all of the saves have completed in the saveInto parameter of the integer field.

    The correct way to achieve the behavior we are looking for would be the following:

    a!localVariables(
      local!number: 0,
      local!message,
      {
        a!integerField(
          label: "Enter number",
          instructions: local!message,
          value: local!number,
          saveInto: {
            local!number,
            a!save(
              target: local!message,
              value: if(
                tointeger(local!number) > 5,
                "This number is greater than five",
                "This number is less than or equal to five"
              )
            )
          }
        )
      }
    )

    In this version, we remove local!greaterThanFive and place the logic directly in our a!save function, which allows for that condition to correctly be evaluated during the save.

  • Thanks for the explanation, now I do understand the logic behind the behavior I get.

    I guess that in order to avoid to duplicate the logic to multiple place I will have to create a rule

  • No problem. Yes - creating a rule would be a good way to simplify the logic. 

Reply Children
No Data