Options

FORM.RunModal(FormID, MyRecord) vs MyForm.RunModal

dorenthasdorenthas Member Posts: 31
Here's a quick and (hopefully) easy question.

In various forms, when I need the user to select a record from another table through a lookup, I do the following if there is no particular processing (no need to call a function on the LookUp form, the LookUp form is a regular tabular form with the usual OK/Cancel buttons, etc.)
// Assuming we have a MyRecord : Record ("My Record") variable
IF FORM.RUNMODAL(FORM::"My Lookup Form", MyRecord) = ACTION::LookupOK THEN BEGIN
  // Do stuff with the selected record
END;

I found our partner usually did the same thing in another way, for the same case (no particular processing).
// Assuming we have a MyRecord : Record ("My Record") variable and a MyLookupForm : Form ("My Lookup Form") variable.
MyLookupForm.SETTABLEVIEW(MyRecord);
MyLookupForm.EDITABLE(FALSE); // Optional - only needed if the LookupForm is also used in another context to modify data
MyLookupForm.LOOKUPMODE := TRUE;
IF MyLookupForm.RUNMODAL = ACTION::LookupOK THEN BEGIN
   MyLookupForm.GETRECORD(MyRecord);
  // Do stuff with the selected record
END;

If all I need a lookup button to do is getting a record without any unusual processing, it seems to me that declaring a Form variable, initializing it, etc. is overkill. Under this hypothesis (i.e. I do not otherwise need the Form variable), are the two above code snippets equivalent?

I looked on mibuso and elsewhere on the web, but couldn't find a definitive answer to my question. In fact, everybody seems to be recommending the second method as the general solution to "lookup a record in another table", but I find it unnecessarily "complex" for the simple case, so I'm wondering if there might be a subtle difference I couldn't find about.

Thanks!

Answers

  • Options
    Slawek_GuzekSlawek_Guzek Member Posts: 1,690
    Hi,

    The code is not exact equivalent. The difference is here:
    MyLookupForm.EDITABLE(FALSE); //disables edit
    MyLookupForm.LOOKUPMODE := TRUE; //shows OK and Cancel buttons
    
    If you do not have to make sure that your lookup form is aways in lookup mode and readonly then it doesn't matter in fact. (MyLookupForm.LOOKUPMODE := TRUE; is enough BTW);

    My personal preference is to use relation (no code at all, only default lookup form provided by NAV), then, if I need to code something extra, use FORM.RUNNODAL(0,rec), then use FORM.RUNNODAL(form::"somespecificformhere",rec), and at last define variable and run MyFormVariable.RUNMODAL construction.

    The main reason for using FORM.RUNNODAL(0,rec) construction is that it works with temporary records passed as rec variable, and uses default lookup form as defined for a table. And it is shorter to write.

    I use MyFormVariable.RUNMODAL constrution only if I need to pass some extra parameters/settings which cannot be passed as a filters, or call form function to prepare lookup, or when it doesn't make sense to create extra fields just to pass some variables.

    Hope this helps.

    Regards,
    Slawek
    Slawek Guzek
    Dynamics NAV, MS SQL Server, Wherescape RED;
    PRINCE2 Practitioner - License GR657010572SG
    GDPR Certified Data Protection Officer - PECB License DPCDPO1025070-2018-03
  • Options
    krikikriki Member, Moderator Posts: 9,096
    There is another difference between
    1) FORM.RUNMODAL
    and
    2) MyFormVar.RUNMODAL

    In 1) the form is initialized ON EACH RUN (this means that the OnInit-trigger of the form will be run each time).
    In 2) the form is initialized ONLY the first time it is run in a certain object. The second time you run it, the OnInit-trigger of the form will NOT run. Of course you can put a CLEAR(MyFormVar) before or after the run. In this case the OnInit-trigger of the form will be run each time. In reality, I consider doing a CLEAR(MyFormVar) after the RUN a good practice.
    Regards,Alain Krikilion
    No PM,please use the forum. || May the <SOLVED>-attribute be in your title!


  • Options
    Slawek_GuzekSlawek_Guzek Member Posts: 1,690
    kriki wrote:
    ...The second time you run it, the OnInit-trigger of the form will NOT run. Of course you can put a CLEAR(MyFormVar)..

    As far as I know MyFormVar.RUNMODAL will NOT run second time, if you don't clear it after first run.

    Slawek
    Slawek Guzek
    Dynamics NAV, MS SQL Server, Wherescape RED;
    PRINCE2 Practitioner - License GR657010572SG
    GDPR Certified Data Protection Officer - PECB License DPCDPO1025070-2018-03
  • Options
    krikikriki Member, Moderator Posts: 9,096
    kriki wrote:
    ...The second time you run it, the OnInit-trigger of the form will NOT run. Of course you can put a CLEAR(MyFormVar)..

    As far as I know MyFormVar.RUNMODAL will NOT run second time, if you don't clear it after first run.

    Slawek
    To be honest, I don't remember if I know cases where I could run it a second time, but I am not sure. Probably it is mandatory to do a CLEAR to run the form a second time.
    Regards,Alain Krikilion
    No PM,please use the forum. || May the <SOLVED>-attribute be in your title!


  • Options
    dorenthasdorenthas Member Posts: 31
    Thanks for your replies!

    I didn't know about the FORM.RUNMODAL(0, MyRecVar) construction. \:D/ So, if I understood Slawek, I could (or is that should?):
      1) use FORM.RUNMODAL(0, MyRecVar) for a simple LookUp.
      2) use FORM.RUNMODAL(FormNo, MyRecVar) for a LookUp using another form than the default form defined for that table.
      3) use MyFormVar.RUNMODAL(MyRecVar) for more elaborate processing, for instance using a non-default LookUp form, call a function of that form, etc.
    kriki wrote:
    ...The second time you run it, the OnInit-trigger of the form will NOT run. Of course you can put a CLEAR(MyFormVar)..

    As far as I know MyFormVar.RUNMODAL will NOT run second time, if you don't clear it after first run.

    Slawek

    I'm pretty certain that is right. If I remember correctly, using MyFormVar.RUNMODAL twice without using CLEAR(MyFormVar) in between causes NAV to throw a run-time error. (So whatever method is used, the OnInit-trigger of the form should always be executed.) However, you can use RUN twice in a row because the variable is automatically cleared when RUN is used (source: C/SIDE Reference Guide).
  • Options
    vasudevapvasudevap Member Posts: 5
    I'm writing my observations from the perspective of TEMPORARY tables:

    For the last little bit I've been grappling with the issue of getting my temporary table to display properly in LOOKUP, and after reading this post, I think I have an understanding of the difference in behavior between FORM.RUNMODAL and MyForm.RUNMODAL:

    For showing temporary records, my observation is that:
    - FORM.RUNMODAL will allow a temporary record to show up correctly, but
    - MyForm.RUNMODAL will only show the main table even if SETTABLEVIEW is issued with the temporary rec as the variable.

    Example:

    TERMINOLOGY USED BELOW:
    {
    RECORDS
    MyTable - not temporary
    MyTEMPTable - temporary version of MyTable

    FORM
    MyForm - default form for MyTable in Object Designer
    MyFormVar - local/global variable for MyForm
    }

    CASE I. When I issue: FORM.RUNMODAL(FORM::MyForm, MyTEMPTable), it works well... it shows me the temporary table, but,

    CASE II. When I issue the following commands:
    CLEAR(MyFormVar);
    MyFormVar.SETTABLEVIEW(MyTEMPTable);
    MyFormVar.RUNMODAL;

    what I see is MyTable, not MyTEMPTable! This had me completely confused for the longest time... I kept thinking that my TRANSFERFIELDS function that I was using to move some lines from MyTable to MyTEMPTable was messed up, but, it was actually a RUNMODAL issue.

    So... fellow developers, BEWARE!
  • Options
    dorenthasdorenthas Member Posts: 31
    Excellent observation!

    So in order to use a Lookup Form with a temporary table, FORM.RUN(FormID, MyRec) or FORM.RUNMODAL(FormID, MyRec) must be used, but this raises another issue to watch for: if the form identified by FormID is a tabular form with the LOOKUPMODE property set to FALSE and EDITABLE to Yes (look at F100 Accounting Periods, for instance, compare with F89 Job List), then you would need to either change the Form properties LOOKUPMODE to Yes and EDITABLE to No (bad idea! this is an invitation to problems due to unforeseen side-effects), or better yet, create a copy of the form in which the properties are set as appropriate for a Lookup Form and use that form instead.

    Given the Accounting Periods example, one would create an Accounting Period List form as a copy of Accounting Periods, set its LOOKUPMODE property to Yes and EDITABLE property to No, then use FORM.RUNMODAL(FORM::"Accounting Period List", MyTEMPTable) to successfully use a Lookup on the temporary table to choose an Accounting Period.
Sign In or Register to comment.