Although you might be aware now that any code in the OnLookup trigger will leave you as a developer to handle everything yourself, you have made the choice to write your own lookup functionality. As mentioned in my previous post OnLookup & OnValidate #1, you not only need to program the look up itself but also have to take care that the selected value is handed over to the field from where the user will perform the lookup, including its validation. Well ... except in the case of programming your lookup code on the relevant form control (see below).
So what exactly does a developer need to take care of when needing to program lookup functionality?
Before we dive into that it’s worthwhile to read this section from the manual of our former "Programming in C/AL" course:
Some application objects have similar triggers, likewise the OnValidate trigger, which exists on tables as field trigger(s) or on forms as control trigger(s). When, after a user action, a value will be validated Attain will execute (in this order)
The OnLookup trigger also exists as field and control trigger. The execution plan, however, is totally different.
Based on this it’s interesting to do some investigations into the validation schema when performing each of the lookups given the fact that both at field and control level the OnValidate trigger has been populated.
When executing a standard lookup the 3 validation levels are executed in this order:
Executing a lookup programmed at field level only 2 validation levels are executed in this order:
No control OnValidate!
And last but not least, when a lookup has been implemented on the control again 3 levels of validation are triggered (and executed):
The code should consist of 3 steps:
Customer No. - OnLookup()Customer."No." := "Customer No.";IF FORM.RUNMODAL(0,Customer) = ACTION::LookupOK THEN VALIDATE("Customer No.",Customer."No.");
The code should consist of 4 steps:
Customer No. - OnLookup(VAR Text : Text;) : BooleanCustomer."No." := "Customer No.";IF FORM.RUNMODAL(0,Customer) = ACTION::LookupOK THEN BEGIN Text := FORMAT(Customer."No."); EXIT(TRUE);END;
Implement your lookup feature as one function on your table so that you can reuse the same function for the OnLookup triggers on the field and control(s).
On the table (field) you could have the following code
Customer No. - OnValidate()// Update some other record(s) in the same table. This will require a form refreshCustomer No. - OnLookup()VALIDATE("Customer No.",LookupCustomerNo("Customer No."));LookupCustomerNo(CurrCustNo : Code) : CodeCustomer."No." := CurrCustNo;IF FORM.RUNMODAL(0,Customer) = ACTION::LookupOK THEN EXIT(Customer."No.");
On the form (control) you would have the following code:Customer No. - OnAfterValidate()CurrForm.UPDATE(FALSE);<Control1000000> - OnLookup(VAR Text : Text;) : BooleanText := FORMAT(LookupCustomerNo("Customer No."));EXIT(Text <> '');
... my good old ex-colleague Gert Robyns (MSFT). Cheers, pal!
Thank you for the article, very nicely explained, it solved my confusion.
By passing the value to the variable Text you ensure that the OnValidate and OnAfterValidate triggers of the control are called and you do not need to duplicate validation code.
Nothing yet. Simply forgotten, so thanx for asking. I have put it on my list.
what did you find out?
Thanx for noting. I'll check it and see what to change in the suggested solution.