Unexpected or wrong xRec in OnModify

s_keims_keim Member Posts: 9
Hello there, (I'm using NAV 2016 (9.00.47838))

I got a strange problem by using xRec in OnModify:
I want to do something only after OnModify if a boolean field is changed: Ensure that only one record is the Default record.
IF Rec.Default AND NOT xRec.Default THEN BEGIN

The problem is: Sometimes are Rec and xRec equal!

Yes, I know that similar questions are spreaded in the www.
Yes I know that the behaviour is different between internal call and external call and GUI call. And normally GUI call should work!
In my case there is only page interaction: Sometimes working, sometimes not working. > Changing behaviour without changing objects!

A simple table:
Only two fields:
  FIELDS
  {
    { 1   ;   ;Code                ;Code10         }
    { 2   ;   ;Default             ;Boolean        }
  }
  KEYS
  {
    {    ;Code                                    ;Clustered=Yes }
  }
Code only in OnModify:
    OnModify=VAR
               TestSKM@50000 : Record 50202;
             BEGIN
               IF Rec.Default AND NOT xRec.Default THEN BEGIN
                 TestSKM.SETFILTER(Code, '<>%1', Code);
                 TestSKM.SETRANGE(Default, TRUE);
                 IF TestSKM.FINDSET(TRUE) THEN
                   REPEAT
                     TestSKM.VALIDATE(Default, FALSE);
                     TestSKM.MODIFY;
                   UNTIL TestSKM.NEXT = 0;
               END;
             END;

And a simple list page created by the wizzard.

So I filled the list with the codes '1', '2', ..., '7'

When setting the Default in a record after leaving the record (MODIFY) all other records should be set to Default = FALSE.

I cannot find a rule. Sometimes it works, sometimes it doesn't work.
Sometimes setting Default from top record to bottom record works.
Sometimes Setting Default from bottom record to top record leaves all record Default = TRUE.

Is there any Explanation?

With kind regards
s_keim
s_keim (Germany)
inhouse developer on NAV2016 (9.00.47838) NAVDE

Answers

  • PhoguePhogue Member Posts: 76
    edited 2020-06-03
    Try creating your own OnModify(xRec) function and moving your code there. It helped me with a very similar issue.


    Edit: Table 5050 has an example of this.
  • s_keims_keim Member Posts: 9
    Hello Phogue,

    thanks for the suggestion, but it will not work.
    As I wrote OnModify is only triggered by user interaction.
    And when in OnModify trigger Rec and xRec are equal than the wrong xRec is forwarded to the OnModify function.

    With kind regards
    s_keim
    s_keim (Germany)
    inhouse developer on NAV2016 (9.00.47838) NAVDE
  • PhoguePhogue Member Posts: 76
    edited 2020-06-03
    s_keim wrote: »
    As I wrote OnModify is only triggered by user interaction.
    You did not write this. Also, you can trigger it programatically by using the RunTrigger parameter:
    Rec.Modify(true)
    
    https://docs.microsoft.com/en-us/dynamics-nav/modify-function--record-
  • s_keims_keim Member Posts: 9
    Hello there,

    to make it clear:

    I wrote: "Code only in OnModify"
    And I wrote: "In my case there is only page interaction"

    My problem is not dysfunction in calling by code. There is dysfunction in user interaction on page.

    When I change and leave a line on page, I don't give the command to modify.
    NAV calls automatically the OnModify trigger without any user-defined code.
    And sometimes Rec and xRec are equal.

    To create a user-defined function OnModify helps in another Scenario.

    With kindly regards
    s_keim
    s_keim (Germany)
    inhouse developer on NAV2016 (9.00.47838) NAVDE
  • PhoguePhogue Member Posts: 76
    edited 2020-06-04
    So if I'm understanding you correctly. The function is being called when you're not manually modifying any values, and you only want it triggered when "Default" is changed

    Instead of
    IF Rec.Default AND NOT xRec.Default
    

    Why not
    IF Rec.Default <> xRec.Default
    
    ?


    Also, regarding your loop
    IF TestSKM.FINDSET(TRUE) THEN
                       REPEAT
                         TestSKM.VALIDATE(Default, FALSE);
                         TestSKM.MODIFY;
                       UNTIL TestSKM.NEXT = 0;
    

    I'd recommend not modifying directly on the same record you're looping through, i.e.
    IF TestSKM.FINDSET(TRUE) THEN
                       REPEAT
                         TestSKM2 := TestSKM;
                         TestSKM2.VALIDATE(Default, FALSE);
                         TestSKM2.MODIFY;
                       UNTIL TestSKM.NEXT = 0;
    
  • s_keims_keim Member Posts: 9
    Hello Phogue,

    in my scenario I have existing records on my list page exactly as in the database.
    I go to a record with Default = FALSE and change it to TRUE.
    I leave the record and OnModify is fired automatically.

    In OnModify should be:
    xRec.Default = FALSE
    Default = TRUE

    But sometimes it isn't.
    sometimes xRec.Default = TRUE.

    That's the problem. The code is only sample code to give you a chance to create an example and test it.

    We can struggle a bit about how to code inside OnModify.
    But the xRec is already wrong.


    About your suggestions:
    Using
    IF Rec.Default <> xRec.Default
    
    I only need to do anything if Rec.Default is TRUE.

    Using a second record variable to modify.
    In former times we should use it. But nowadays it is not neccessary.
    FINDSET(TRUE) is given for the possibility to change the record variable itself.

    But these statements only by the way. My topic is the wrong xRec.


    With kindly regards
    s_keim
    s_keim (Germany)
    inhouse developer on NAV2016 (9.00.47838) NAVDE
  • ACaignieACaignie Member Posts: 91
    If you want to be sure of the previous value of the record it is better to define a record variable of the same subtype as the table, do a GET, and compare the new value with the record var.
    So your example would be:

    TestSKM.GET(Rec.Code);
    IF Rec.Default AND NOT TestSKM.Default THEN BEGIN
    TestSKM.SETFILTER(Code, '<>%1', Code);
    TestSKM.SETRANGE(Default, TRUE);
    ...
  • PhoguePhogue Member Posts: 76
    edited 2020-06-05
    What about subscribing to the OnBeforeModify event on the field?

    LOCAL [EventSubscriber] TestSKMOnBeforeModify(VAR Rec : Record TestSKM;VAR xRec : Record TestSKM;RunTrigger : Boolean)
      xRec.GET(Rec.Code);
      MESSAGE('xRecBeforeModifyEvent: '+ format(xRec.Default) + '\RecBeforeModifyEvent:'+ format(Rec.Default);
    
  • s_keims_keim Member Posts: 9
    Hello ACaignie and Phogue,

    surely both your suggestions would work. I already thought about it.

    And if there is no better solution I would have to do it.

    Why I'm hesitating?
    My GET would be used in any modification case not only when Default is changed ...

    And what bothers me is: When can I trust in xRec?
    There are different results in calling by internal code.
    But page interaction should work.

    With kindly regards
    s_keim
    s_keim (Germany)
    inhouse developer on NAV2016 (9.00.47838) NAVDE
Sign In or Register to comment.