Most of Dynamics AX data
lookups display a list of records where the first column always contains
a value, which is returned to a calling form. The first column in the
lookup normally contains a unique record identification value, which is
used to build relations between tables.
For example,
customer lookup displays customer account number, customer name, and
some other fields; inventory item lookup displays item number, item
name, and other fields. In these examples and most other cases, it is OK
because unique record identification value is self explanatory.
But in some cases, the
record identifier can be not so user-friendly and may require showing
additional information on the parent form. One of the ways of solving
such issues is to create a lookup, which is actually based on the record
identifier, but upon user selection returns the record description or
other more explanatory field. In the standard Dynamics AX application,
you can find a number of places where the contact person is displayed as
a person name, even though the actual table relation is based on
contact person ID.
In this recipe, we will replace language selection lookup on Vendors form to show language description instead of language ID.
How to do it...
1. Create a new String extended data type:
Property
|
Value
|
---|
Name
|
LanguageDescriptionExt
|
Extends
|
LanguageDescription
|
Label
|
Language
|
2. Open the VendTable table in AOT, and add a new edit method:
client server edit LanguageDescriptionExt editLanguage (
boolean _set,
LanguageDescriptionExt _languageDescription)
{;
if (_set)
{
this.LanguageId = _languageDescription;
}
return LanguageTable::languageId2Description(
this.LanguageId);
}
3. Open the VendTable form in AOT, and modify the LanguageId control properties in the following way:
Property
|
Value
|
---|
Visible
|
No
|
4. Create a new control of type StringEdit right below the LanguageId control with properties as shown below:
Property
|
Value
|
---|
Name
|
editLanguage
|
DataSource
|
VendTable
|
DataMethod
|
editLanguage
|
5. Override the editLanguage contol's lookup() method with:
public void lookup()
{;
this.performTypeLookup(extendedtypenum(LanguageId));
}
6. After all modifications, the VendTable form should look like this in AOT:
Next open Accounts payable | Vendor Details, go to the General tab page, and check the newly created Language lookup:
How it works...
In this recipe, we are using the edit
method to display a language description instead of the language ID.
The language description is based on the extended data type LanguageDescription, which has the label Description. In order to change that label, we create a new extended data type called LanguageDescriptionExt with the right label— Language.
The edit method is created on VendTable
and uses the newly created extended data type. This ensures that the
label of the user control stays the same. Note that this method accepts a LanguageDescriptionExt extended data type as its second argument, but actually it receives a LanguageId returned from the lookup. This is totally fine, because both types are based on the string basic type and LanguageId is less in size. The method returns a language description based on the language ID.
We have almost everything ready, and now we need to adjust the VendTable form to show the new field. First, we hide the existing LanguageId control by setting its Visible property to No. Then we create a new control that points to the edit method on the VendTable table. This ensures that the language description is shown on the control.
The last thing to do is to override the lookup() method to make sure the control allows the user to select a language. Here we use performTypeLookup() to invoke automatic LanguageId lookup. As described earlier, the lookup return value is of type LanguageId, and it is passed to the edit method for further processing.
One thing to mention here is that the edit (and display)
methods might affect system performance, especially when dealing with
great amounts of data when they are added, for example, to the form
overview screen.
There's more...
In the previous example, you
may have noticed that the language lookup sometimes does not find or
finds incorrectly the currently selected language. In the previous
screenshot, current language is set to English (United States), but once opened, the focus of the lookup is placed on English (Ireland). It happens because the system "thinks" that the current language ID is English (United States),
tries to find that ID in the list of languages, which is obviously not
there, and once it is not found, it picks up the closest match.
The instructions in
this section will show us how to solve this issue. The principle is that
we need to create a new custom lookup form and select the current
language record by calling findValue() on the LanguageTable form data source.
So let's create a new AOT form named LanguageLookup. Add a new data source with the following properties:
Property
|
Value
|
---|
Name
|
LanguageTable
|
Table
|
LanguageTable
|
Index
|
Key
|
AllowCreate
|
No
|
AllowDelete
|
No
|
AllowEdit
|
No
|
AllowCheck
|
No
|
Add a new grid to the form's design:
Property
|
Value
|
---|
Name
|
Languages
|
ShowRowLabels
|
No
|
DataSource
|
LanguageTable
|
DataGroup
|
Languages
|
Once the form is saved, two new controls should appear in the grid automatically. Change the properties of Languages_LanguageId:
Property
|
Value
|
---|
AutoDeclaration
|
Yes
|
Override the form's init() and run() with the following code:
public void init()
{;
super();
element.selectMode(Languages_LanguageId);
}
public void run()
{
LanguageId languageId;
;
languageId = element.args().lookupValue();
super();
LanguageTable_ds.findValue(
fieldnum(LanguageTable,LanguageId), languageId);
}
The key element is LanguageTable_ds.findValue() in the form's run(), which sets the cursor on the currently selected language record. Language ID is retrieved from the arguments object by using lookupValue().
In AOT, the form should look like this:
Next, we need to create a new static method in the LanguageTable table, which opens the new lookup form:
public client static void lookupLanguage(
FormStringControl _callingControl,
LanguageId _languageId)
{
FormRun formRun;
Args args;
;
args = new Args();
args.name(formstr(LanguageLookup));
args.lookupValue(_languageId);
formRun = classfactory.formRunClass(args);
formRun.init();
_callingControl.performFormLookup(formRun);
}
Here, we use the formRunClass() method of global classfactory object. Note that the second argument of this method is of type LanguageId, and it is passed to the newly created form by using lookupValue() via the args argument object.
The final touch is to change the code in the lookup() of editLanguge on the VendTable form, which invokes the new lookup form:
public void lookup()
{;
LanguageTable::lookupLanguage(this, VendTable.LanguageId);
}
Now, when you open Accounts receivable | Vendor Details, the currently set vendor language in the Language lookup will be preselected correctly: