martedì 15 gennaio 2013

AX 2009 - Creare un form di lookup

Con questo post ho colto l'occasione per documentare una modifica abbastanza frequente ed utile, almeno per la mia esperienza. Ho ripreso un post già esistente (http://axaptapedia.com/Lookup_Form) che però faceva riferimento a più versioni di AX e che in parte era ormai obsoleto su AX2009. Con l'occasione ho tradotto il post in italiano e riadattato il contenuto al pieno funzionamento sulla versione AX2009, per le versioni precedenti rimando la lettura al post originale di cui ho esso il link.

Nell'esmpio sotto vedremo come creare una lookup per un'ipotetica tabella "Table" con campo chiave "Id". Il campo "Id" dovrà essere una stringa.
Come prima cosa dovremo creare un form molto semplice che conterrà nella maggior parte dei casi solo una griglia contenente i campi che vogliamo mostrare. Nella figura sotto è mostrato come impostare alcune proprietà del datasource:


Dovremo poi impostare come di seguito alcune proprietà nel design del form:


Assiamiamo che il nostro form di lookup abbia un control di tipo grid, e che in questo sia presente un control che punta al campo chiave che vogliamo utilizzare. Tale campo per comodità lo rinominiamo come "Table_Id" e impostiamo la proprietà 'AutoDeclaration' dello stesso a true.

Andremo adesso a modificare alcuni metodi del nostro form.

Override del metodo 'init' del form, in questo modo andremo ad impostare quel'è il controllo che sarà il risultato della nostra selezione.

 public void init()  
 {  
   ;  
   super();  
   element.selectMode(Table_Id);  
 }  

Override del metodo 'executeQuery' del datasource 'Table' del nostro form (ci permetterà di impostare il valore selezionato nel controllo chiamante come filtro della nostra form di lookup):

 public void executeQuery()  
 {  
   FormStringControl  callerControl  = SysTableLookup::getCallerStringControl(element.args());  
   ;  
   super();  
   Table_ds.findValue(fieldnum(Table,Id),callerControl.text());  
 }  

e del metodo 'init' del nostro dataSource (dove possiamo impostare la nostra query custom, definendo filtri, ordinamenti, ecc...):

 public void init()  
 {  
   Query        q = new Query();  
   QueryBuildDataSource qbds;  
   ;  
   super();  
   qbds = q.addDataSource(tablenum(Table));  
   qbds.orderMode(OrderMode::OrderBy);  
   qbds.addSortField(fieldNum(Table, some_other_field));  
   this.query(q);  
 }  

Se vogliamo inoltre rendere disponibili le wildcard (eg. "abc*" )per il filtro su stringhe, come concesso a standard da Ax, dovremo effettuare l'override del metodo 'run' del nostro form di lookup come segue:

 public void run()  
 {  
   FormStringControl  callerControl  = SysTableLookup::getCallerStringControl(element.args());  
   Boolean       filterLookup  = false;  
   ;  
   // if lookup was called with filter, then supress autoSearch  
   if (callerControl.text() && callerControl.hasChanged())  
   {  
     filterLookup = true;  
     Table_ds.autoSearch(false);  
   }  
   super();  
   // after call of super filter search manually by applying past filter  
   if (filterLookup)  
   {  
     Table_ds.research();  
     Table_ds.filter(fieldnum(Table, Id),callerControl.text());  
   }  
 }  

Se vogliamo che il form appena creato diventi il default per un determinato Extended Data Type dovremo semplicemente impostare il nome del nostro form nella proprietà 'FormHelp' del EDT.

Se, in alternativa, vogliamo utilizzare la nostra lookup in un controllo specifico, lasciando di default la lookup standard di AX, dovremo andar a customizzare il metodo lookup del nostro chiamante.
Definito per comodità il controllo chiamate come "CallerTable_CallerId" e impostata la proprietà 'AutoDeclaration' dello stesso a true, dovremo andare a modificare il metodo lookup del campo ad esso associato come segue. Nell'esempio la tabella chiamante sarà "CallerTable", il campo "CallerId" e datasource "CallerTable_DS".

 public void lookup(FormControl _formControl, str _filterStr)  
 {  
   Args args = new Args();  
   FormRun itemLookUp;  
   ;  
   args.name(formstr(CustomLookupForm));  
   args.caller(CallerTable_CallerId);  
   itemLookUp = new FormRun(args);  
   itemLookUp.init();  
   this.performFormLookup(itemLookUp, CallerTable_CallerId);  
 }  

 public void performFormLookup(FormRun _form, FormControl _formControl)  
 {  
   super(_form, _formControl);  
 }  

Avrete in questo modo un form di lookup custom perfettamente funzionante.