Overview

Widget Lookup

Widget colonna per relazioni (lookupByID, multiple_check) con tab dedicato Lookup nel metadata-editor colonne.

Esempi

Quando usarlo

  • selezione record correlati da tabella metadata esterna.
  • scenari con ricerca lato server e paging lookup.
  • supporto singola selezione (lookupByID) e multi selezione (multiple_check).

Proprieta metadata colonna (tab Lookup)

  • mc_ui_lookup_entity_name: route metadata sorgente lookup.
  • mc_ui_lookup_dataValueField: campo ID restituito.
  • mc_ui_lookup_dataTextField: campo descrizione mostrata.
  • mc_ui_lookup_computed_dataTextField: espressione SQL per il testo mostrato (override di mc_ui_lookup_dataTextField). Referenzia i campi della tabella correlata con l'alias di join <colonna>_<entity>, es. UPPER([StateProvinceID_stateprovinces].[StateProvinceName]). Via chatbot l'alias si ottiene con request_metadata_detail{detail:'lookup_columns'}.
  • mc_ui_lookup_filter: filtro base lookup.
  • mc_serverside_operations: ricerca/paging server-side.
  • mc_ui_pagesize: dimensione pagina risultati lookup.
  • mc_ui_lookup_edit_allow: abilita edit record lookup da popup.
  • mc_ui_lookup_insert_allow: abilita inserimento record lookup da popup.
  • mc_ui_lookup_search_grid: abilita griglia di ricerca nel popup.
  • mc_logic_allow_navigation: navigazione su route collegata.

mc_props_bag utile

Snippet 1JSON
{
  "lookup": {
    "filter": {
      "logic": "AND",
      "filters": [
        { "field": "is_active", "operatore": "eq", "value": true }
      ]
  • lookup.filter: vincolo aggiuntivo lato client/server nella query lookup.
  • lookup.virtualize: abilita virtual scroll su p-autocomplete del widget lookup.
  • lookup.virtualize.enabled: parser tollerante (true/false, 1/0, stringhe equivalenti); default false quando assente.
  • lookup.virtualize.itemSize: altezza riga virtuale in px; default 44.
  • lookup.endpoint: override provider dati del dropdown. Quando settato, il nested datasource del lookup-editor non passa piu' dal combo endpoint metadata (MetaService.getFlatRecordComboData) ma direttamente dal provider dichiarato in type con la URL in uri.
  • lookup.endpoint.type: 'odata' (dispatcher instrada a DataProviderOdataService.selectCombo che emette GET con $top, $count=true, $select=valueField,textField e $filter=contains(textField,'<query>') per la server-side search). Altri valori seguono la stessa logica del table-level extraProps.endpoint.type.
  • lookup.endpoint.uri: URL base dell'entity set (es. /odata/<EntitySet>), con o senza origine esplicita. Query params esistenti vengono ignorati — il provider ricostruisce i params ad ogni fetch.
  • form.columns: larghezza campo nel form edit.
  • style.editCss: stile custom editor.

Combo slim — campi extra via mc_props_bag.slimCombo

Il dropdown lookup di default fa un SELECT minimale sulla tabella correlata: PK + mc_ui_lookup_dataValueField + mc_ui_lookup_dataTextField. Riduce il payload del combo. Se il client ha bisogno di altri campi della tabella correlata — tipicamente per pre-popolare colonne dipendenti via mc_selection_changed_custom_function__fn — si usa mc_props_bag.slimCombo come array di nomi colonna extra da includere nel SELECT del combo:

Snippet 2JSON
{
  "slimCombo": ["unita_misura_id","codice_iva_id","prezzo_vendita","sconto_default"]
}
  • Array: i nomi vengono aggiunti al columnRestrictionList del combo response (logica in DataProviderMetaService.buildSlimComboRestriction).
  • slimCombo: false: disabilita la restrizione → il combo ritorna tutte le colonne. Utile in debug, payload piu' grande.
  • Se la colonna ha mc_ui_lookup_combo_text_edit_computed_dataTextField valorizzato (formula display computata), slimCombo viene ignorato e il combo ritorna tutte le colonne (la formula puo' referenziare campi arbitrari).

I campi extra finiscono in record['<col>__lookup_obj'].value (record pieno della tabella correlata, gia' completo dei campi dichiarati in slimCombo) e sono accessibili dal callback mc_selection_changed_custom_function__fn:

Snippet 3ts
prodCol.mc_selection_changed_custom_function__fn = (record, _f, _m, newValue) => {
  const prod = record['prodotto_id__lookup_obj']?.value;
  if (!prod) return;
  record['descrizione']?.next(prod.descrizione);
  record['prezzo_unitario']?.next(prod.prezzo_vendita);
  record['unita_misura_id']?.next(prod.unita_misura_id);
  record['codice_iva_id']?.next(prod.codice_iva_id);

Tradeoff: payload combo leggermente piu' grande ma niente HTTP roundtrip aggiuntivo (getFlatRecordData per recuperare il record pieno per id) ad ogni selezione.

Workflow Assistito: Clone Lookup + Filtro Default + Lookup Hierarchy

  • Flusso operativo inline: suggestLookup2 -> suggestLookupDefaultFilter -> getLookupListByRoute -> getSeletClauseByLookupHierarchy.
  • Snippet inline campi principali: mc_ui_lookup_entity_name, mc_ui_lookup_dataValueField, mc_ui_lookup_dataTextField, mc_ui_lookup_filter.
  • Snippet inline filtro rapido: lookup.filter: {"logic":"AND","filters":[{"field":"is_active","operatore":"eq","value":true}]}.
  • Effetto client: setup lookup accelerato nel metadata-editor e filtro coerente gia pronto nel widget.
  • Effetto server: query lookup e select clause restano allineate agli endpoint MetaService.* senza mapping manuale.

Checklist operativa rapida:

1. clonare configurazione base con suggestLookup2;

2. generare filtro default con suggestLookupDefaultFilter;

3. rifinire gerarchia/select clause dal tree lookup;

4. validare in runtime che ricerca e value/text mapping siano coerenti.

Effetti Client/Server

  • Client: rendering widget lookup, search, etichetta/value binding.
  • Client: con lookup.virtualize attivo, l'autocomplete renderizza solo il subset visuale delle opzioni.
  • Server: query lookup paginata/filtrata tramite MetaService.getFlatRecordData.

Note operative

  • in multiple_check la parte lookup resta la stessa, cambia il renderer multi valore.
  • se manca mc_ui_lookup_entity_name, il widget non puo risolvere la sorgente.

Auto-fetch su FK programmatici

Il wuic-lookup-editor sottoscrive automaticamente al BehaviorSubject di record[mc_nome_colonna] e gestisce i cambi di FK programmatici (es. import documento sorgente, callback custom che setta record.cliente_id.next(99)):

  • Se il nuovo valore e' gia' presente in `items` (la pagina caricata della lookup): popola solo __lookup_obj per coerenza, niente HTTP.
  • Se il nuovo valore non e' negli items (es. valore fuori dalla pagina corrente del combo, o non ancora fetchato): scatta una second-stage fetch filtrata WHERE <valueField> eqor <newValue> per recuperare il record correlato e popolare automaticamente il dropdown.

Skip cases (no-op):

  • Lookup multi-value (isFilter con eqor, multiple_check)
  • Prima emit del BS (gia' coperto dal flow init)
  • Valore null/undefined (utente ha clearato)
  • hasActiveLookupQuery=true (utente sta typing una query manuale)

Implicazione per i custom form: settare solo il FK basta — non servono piu' workaround manuali per popolare __lookup_obj o l'alias joined. Il display del dropdown si aggiorna da solo.

Snippet 4ts
// PRIMA (workaround manuale richiesto)
record.cliente_id.next(99);
record.cliente_id__lookup_obj.next({ id: 99, ragione_sociale: 'Acme S.r.l.' });
record['clienti___ragione_sociale__cliente_id'].next('Acme S.r.l.');

// ORA (auto-fetch del lookup-editor)
record.cliente_id.next(99);

> Nota: l'auto-fetch fired solo quando il <wuic-lookup-editor> e' montato (cella in edit mode). Per il display in lista (cella read-only), formatGridViewValue legge l'alias joined <route>___<textField>__<col> direttamente dal record — quello va comunque popolato manualmente se non viene dal backend.

Screenshot

field-widget-lookup / field-editor-lookup-tab
field-widget-lookup / field-editor-lookup-tab