• IT
betterdocs-cat-icon 1-svg

Qualcosa è andato storto?

Condividi con noi la tua opinione per migliorare la nostra documentazione.

    Getting Started

    • Introduzione Instant Developer Cloud
    • Composizione della piattaforma
    • Struttura dei progetti
    • La programmazione relazionale
    • Apprendere l’uso di Instant Developer Cloud

    Struttura di un'applicazione

    • Introduzione (applicazione e sessione)
    • Le videate
    • Classi e librerie
    • Risorse e CSS
    • I pacchetti
    • Programmazione asincrona

    Struttura del database

    • Introduzione (struttura del database)
    • Definizione degli schemi relazionali
    • Scrittura di query ed esecuzione di comandi
    • Gestione dei database nel cloud
    • Il Cloud Connector

    Document Orientation

    • Introduzione Document Orientation
    • Definire Documenti e Collection
    • Utilizzo dei documenti
    • Estensione dei documenti

    Datamap

    • Introduzione Datamap
    • Creazione di liste di documenti
    • Modifica dei documenti con videate di dettaglio
    • Datamap innestate e ricorsive

    IonicUI

    • Introduzione IonicUi
    • Le pagine IonicUI
    • Definire il contenuto delle pagine
    • Il page controller
    • Il metodo app.popup
    • Videate come elementi visuali
    • Personalizzazione di IonicUI
    • Configurazione dei ruoli e degli accessi

    Pannelli e Griglie

    • Introduzione (Pannelli e Griglie)
    • Anatomia di un pannello
    • I pannelli a runtime

    Web API e file system

    • Introduzione Web API
    • Il file system
    • Consumare Web API
    • Esporre Web API
    • Web API in formato OData
    • Utilizzare Web API Instant Developer Foundation
    • Web API in formato OpenAPI

    Sincronizzazione

    • Introduzione sistema di sincronizzazione
    • Scambio di messaggi in tempo reale
    • Document Orientation Remota
    • Sincronizzazione del database offline

    Debugging e Test

    • Introduzione Debugging e Test
    • Strumenti e tecniche di debug
    • Test automatico delle applicazioni

    Traduzioni

    • Introduzione (traduzioni)
    • Processo di traduzione
    • Funzionamento del framework di localizzazione
    • Localizzazione di numeri e date

    Integrazioni di componenti esterni

    • Introduzione (integrazioni di componenti esterni)
    • Integrazione di componenti JavaScript
    • Integrazione di librerie di back-end
    • Integrazione di un plugin Cordova

    Launcher e Pubblicazione

    • Introduzione Launcher
    • I plugin nativi
    • Test delle applicazioni nei launcher
    • Pubblicazione sugli store
    • Configurazioni per gli store
    • Fase di build e di invio
    • Gestione dell’applicazione

    Analitiche e Feedback

    • Introduzione Analytics e Feedback
    • Installazione ed uso di Analytics
    • Raccolta dei feedback degli utenti

    Server di Produzione

    • Introduzione server di produzione
    • I server di Instant Developer Cloud
    • I server My Cloud
    • I server Self Managed
    • Tabella comparativa

    Cloud Connector

    • Cos’è il Cloud Connector
    • Installazione Cloud Connector
    • Configurazione
    • Installazione come servizio
    • Esempio di utilizzo
    • Controllo remoto
    • Note

    Team Works

    • Perché non basta GitHub?
    • Team Works: concetti base
    • Organizzazione del lavoro consigliata
    • Risoluzione dei problemi relativi a Team Works
    • Domande sull’utilizzo di Team Works

    Manuale PWA

    • Cos’è una PWA?
    • Creazione di una PWA su Instant Developer Cloud
    • Life Cycle
    • Installazione PWA
    • Funzionalità
    • Plugin
    View Categories

    Modifica dei documenti con videate di dettaglio

    Contenuti
    • Gestione delle modifiche pendenti
    • Gestione dello stato dei pulsanti dell’intestazione
    • Selezione di dati provenienti da altre tabelle
      • Uso di controlli di tipo autocomplete
      • Uso di datamap basate su documenti e controlli di tipo autocomplete
      • Selezione di dati provenienti da altre tabelle in layout lista

    In questo paragrafo ripercorriamo i concetti illustrati nei paragrafi precedenti applicandoli ad un caso molto comune: la modifica di un documento tramite una videata di dettaglio. Nell’immagine seguente possiamo vedere una struttura di esempio.

    VUi9B5xQCqwStALcQLm50OTMrh2UXwE bgawQstyd2m6wqIR38GUYBzrWEyk0Zwk98vrp7SHAxrbgc4YPTFL88G1z pmeXNH10MeahATQPTih3dW93puyH8yD2 Z6JKtNYIr H8rGyYkEictyOqnmw Instant Developer

    La videata di dettaglio contiene i seguenti oggetti:

    1. Una proprietà di videata che referenzia il documento da modificare (in questo caso è la proprietà product).
    2. L’evento onLoad che permette di leggere il prodotto da modificare e di inizializzare la datamap.
    3. Gli elementi visuali che servono per modificare i dati (in questo caso tre IonInput e un IonCheckbox). Tali elementi sono collegati alle relative proprietà del documento Product tramite la datamap.
    4. La datamap che permette di visualizzare e modificare il documento. In questo caso si chiama dmProdotto; si noti che nelle proprietà viene impostato il Tipo contenuto ma non viene indicato alcun Template di riga.
    5. I pulsanti nell’intestazione per salvare le modifiche o cancellare il documento.

    Per attivare il dettaglio, la videata ListaProdotti intercetta il clic su una riga della lista e apre la videata di dettaglio. Si noti che per navigare fra le videate viene usato App.Pages, un oggetto NavigationController che verrà illustrato nel capitolo relativo al framework IonicUI.

    Il codice dell’evento onClick sull’item della lista è quindi il seguente:

    $item.onClick = function (event)
    {
      App.Pages.push(app, App.DettaglioProdotto, {doc : this.row.document});
    };

    Possiamo notare che fra le opzioni per la nuova videata viene passata anche la referenza al documento Product collegato alla riga della lista che viene cliccata (this.row.document). L’effetto è il seguente:

    image10 Instant Developer

    Il codice da scrivere per ottenere questo risultato è veramente limitato. Nell’evento onLoad della videata, viene semplicemente collegato il documento passato dalla lista alla datamap dmProdotto.

    App.DettaglioProdotto.prototype.onLoad = function (options)
    {
      view.product = options.doc;
      $dmProdotto.document = view.product;
      $title.innerText = view.product.ProductName;
    };

    È importante ricordare che per ottenere la visualizzazione dei dati del prodotto è necessario collegare a design time le proprietà della datamap agli elementi visuali corrispondenti tramite la Sorgente dati, come vediamo nell’immagine seguente relativa al nome del prodotto.

    Inoltre notiamo che siccome la datamap non ha un template, essa non effettua alcuna operazione di clonazione per la generazione delle righe, ma semplicemente opera sugli elementi già esistenti nella videata. Ecco perché una datamap senza template è la struttura adatta ad una videata di dettaglio.

    kOhaHLBGX3cdrnRsweq Bnfyd2WJ5kwlM4mio4PcqB1Ny7eNtHjw8ybnwg0e2VN Instant Developer

    Vediamo adesso il codice dei pulsanti di conferma modifiche e di cancellazione:

    $btnSave.onClick = function (event)
    {
      let b = yield view.product.save();
      if (b) {
        App.Pages.pop(app);
      }
    };

    Si può notare che viene salvato direttamente il documento product invece che la datamap. Avremmo potuto salvare i dati anche scrivendo $dmProdotto.save(), ma abbiamo scelto una via più diretta. Se il salvataggio ha successo, la videata viene chiusa e si ritorna alla lista.

    Vediamo ora il codice per cancellare il prodotto:

    $btnDelete.onClick = function (event)
    {
      view.product.deleted = true;
      yield $btnSave.onClick();
    };

    Esso viene marcato per la cancellazione e poi si procede come nel caso di salvataggio delle modifiche. 

    Si noti che il codice mostrato è solo esemplificativo. Nei casi reali occorre chiedere conferma e gestire eventuali errori di salvataggio o cancellazione.

    Provando la videata a runtime è interessante notare che modificando il nome del prodotto nella videata di dettaglio, tale modifica viene riflessa automaticamente anche nella videata in lista, in quanto la stessa istanza del documento prodotto è parte della sorgente dati di entrambe le datamap, quella della lista (dmProdotti) e quella del dettaglio (dmProdotto). Se quindi una delle due datamap ne modifica le proprietà, anche l’altra se ne accorge e sincronizza la corrispondente parte visuale in autonomia.

    Gestione delle modifiche pendenti #

    In queste videate può essere interessante controllare il pulsante back che permette di ritornare alla lista, presente nella videata al momento della creazione della pagina. Se infatti l’utente modifica i dati del prodotto e poi torna indietro senza prima confermare le modifiche, è opportuno avvertire che esse verranno perse, e poi effettivamente annullarle prima di tornare alla lista.

    Il codice da utilizzare è il seguente:

    $navbar.onBackButton = function (event)
    {
      if (view.product.isModified()) {
        let b = yield app.confirm("Tornando alla lista perderai le modifiche.
                                   Vuoi continuare?");
        if (!b)
          return;
        view.product.restoreOriginal();
      }
      App.Pages.pop(app);
    };

    L’evento onBackButton viene notificato quando l’utente preme il pulsante back nell’intestazione. Nell’implementazione mostrata, viene controllato se il documento è stato modificato e in tal caso si chiede conferma all’utente se vuole veramente uscire. Se l’utente risponde “No”, l’evento termina senza chiudere la videata. Se invece l’utente conferma l’uscita, le modifiche al documento vengono annullate tramite il metodo restoreOriginal e poi la videata di dettaglio viene chiusa.

    Gestione dello stato dei pulsanti dell’intestazione #

    Un’ulteriore caratteristica che può migliorare l’esperienza utente è quella di visualizzare i pulsanti dell’intestazione in funzione dello stato del documento. In particolare, il pulsante di salvataggio può apparire solo se il documento è stato modificato, mentre quello di cancellazione solo se il documento non è stato modificato.

    Per ottenere questo comportamento possiamo implementare l’evento onDataChange, che viene notificato ogni volta che cambia il contenuto della sorgente dati della datamap.

    $dmProdotto.onDataChange = function ()
    {
      let mod = view.product.isModified();
      $btnSave.visible = mod;
      $btnDelete.visible = !mod;
    };

    Selezione di dati provenienti da altre tabelle #

    Vediamo infine come implementare elementi visuali per la modifica dei dati quando essi sono basati su dati provenienti da altre tabelle. Ad esempio, possiamo implementare la selezione della categoria del prodotto tramite un elemento di tipo IonSelect.

    Jo5la 0BHGgyk5eUwW5rUJc06OHwc99IHKLrg g49lUpIdOp4bivFXIJa5sL6YeHR sB3hMFdLB92DtfphLJuIvDa byoc vtiodhBiVdMk3NhsGt86dKbQcUN8PzGR2mJdofrk5O4Uof1Hvl4bGmg Instant Developer

    Nell’immagine possiamo notare che l’elemento select, di tipo IonSelect, ha come Sorgente dati la proprietà CategoryID del prodotto; inoltre esso contiene una datamap chiamata vlCategory, acronimo di lista valori delle categorie. Le uniche proprietà impostate di questa datamap sono AutoLoad a true e Tipo contenuto al documento Category.

    Vediamo quindi un terzo tipo di utilizzo delle datamap: esse possono fungere da sorgente dati per un determinato elemento visuale. Possiamo riconoscere questa modalità di funzionamento dal fatto che esse non compaiono al primo livello, subito sotto la videata, ma all’interno dell’elemento che devono servire.

    Quando la videata si apre, la datamap vlCategory effettua il caricamento dei suoi dati e poi li invia come lista valori alla IonSelect che li utilizzerà per decodificare il valore di CategoryID del prodotto in fase di modifica, e anche per consentire all’utente di scegliere un’altra categoria.

    Possiamo vedere il risultato nell’immagine seguente:

    G6KEfj1VixTW1MsxTNa7D3 ZQeEC7URx6jIJa2NmJWc5UbrSeHpNOxVVd7mySTj68 AmdxSKCjHV3LpLYoPNOK2rUmtiVspMv9CprF09mdhm3eSBsBUzYo7v fKUQ4ze7pxc8 pNnJDnLKbWfGeaew Instant Developer

    Notiamo che questo è un modo semplice di ottenere il risultato, ma è utilizzabile solo in alcuni casi. Infatti la datamap vlCategory carica i dati di tutte le categorie, che in questo caso sono solo 9 e quindi è accettabile. Inoltre non carica solo i campi CategoryID e CategoryName, ma tutte le colonne della tabella Categories. Un modo più performante può essere quello di utilizzare una query strutturata al posto di indicare il documento nella proprietà Tipo contenuto della datamap.

    Possiamo notare che è possibile controllare le datamap usate come lista valori come tutte le altre datamap. Se, ad esempio, dovessimo implementare una select la cui lista valori dipende da quello che viene selezionato in un’altra select, non dovremmo fare altro che implementare l’evento onChange della seconda select e in esso ricaricare la datamap della prima select con i dati appropriati.

    Uso di controlli di tipo autocomplete #

    Una soluzione più adeguata al caso di selezione dati da una tabella molto grande si può ottenere utilizzando un elemento IonAutoComplete che contiene una datamap basata su una query strutturata dipendente dal valore dell’elemento stesso, come mostrato nell’immagine seguente.

    Le proprietà della datamap sono AutoLoad impostata a true e maxRows impostata a 30. Al momento dell’apertura della videata la datamap esegue il caricamento e, siccome la query strutturata ha una dipendenza dal valore della proprietà value dell’elemento visuale autocomplete, essa installa un osservatore su tale proprietà: in questo modo tutte le volte che la proprietà cambia, la query verrà automaticamente eseguita. 

    bX5sCKZi0MMNdR9jf0XRJN41NFsksng52PiOu44tiRfG9Vj3gIRdSGQb92PT6oQy0NHXn6gn52S28yjyRk2TUktn20iFMu42E8kXjQ CfVFE1rxxMuKcWnd7J8N8uCxmshb2U SU0KQVXt bL6UEQ Instant Developer

    La clausola where dipendente dal valore dell’autocomplete fa sì che la datamap esegua delle query mirate alla decodifica del valore della proprietà SupplierID caricando però solo i dati che servono. La query effettuata da vlSupplier all’apertura della videata è la seguente:

    select SupplierID, CompanyName from Suppliers where SupplierID = 1 limit 30

    È un caricamento con selezione per chiave primaria, accettabile anche se la tabella Suppliers avesse milioni di righe. Oltre alla visualizzazione della decodifica del valore, l’accoppiamento fra autocomplete e datamap attiva altre due modalità di funzionamento. 

    La prima modalità entra in gioco quando l’utente clicca sull’autocomplete se essa ha la proprietà OpenOnFocus attivata. In tal caso, infatti, l’utente si aspetta di vedere tutti i fornitori dell’archivio. Questo non è possibile se essi sono migliaia, ma comunque viene caricata la lista dei primi 30 in modo tale da soddisfare le aspettative dell’utente. Al momento del clic sull’autocomplete, la query eseguita è quindi la seguente:

    select SupplierID, CompanyName from Suppliers limit 30

    Quando l’utente comincia a scrivere nella parte di input dell’autocomplete, si attiva una seconda modalità di funzionamento nella quale la datamap cerca i record richiesti dall’utente eseguendo una serie di query sulla tabella Suppliers fino a trovare almeno un record. Scrivendo, ad esempio, la lettera E, la datamap esegue le seguenti query:

    select SupplierID, CompanyName from Suppliers where (CompanyName = 'e') limit 30
    select SupplierID, CompanyName from Suppliers where (CompanyName ILIKE 'e%') limit 30

    Dopo la seconda query non ne vengono eseguite altre perché vengono trovati dei dati. In caso contrario la datamap continuerebbe ad eseguire altre query utilizzando operatori più inclusivi, come ad esempio:

    CompanyName ILIKE '%e%'. 

    È possibile controllare da codice questo procedimento implementando l’evento onSearch della datamap oppure tramite l’evento onFilter dell’elemento IonAutoComplete.

    Si noti infine che la query della datamap può contenere altre clausole where, sia collegate ad elementi visuali che ad altre proprietà della videata. In questo modo è possibile implementare elementi di ricerca basati su dati contenuti in altri elementi o comunque in un contesto specifico.

    Uso di datamap basate su documenti e controlli di tipo autocomplete #

    Nel paragrafo precedente abbiamo visto l’utilizzo di una datamap basata su query come sorgente di valori per un elemento IonAutoComplete: se la query contiene una clausola where collegata all’elemento, si attiva una modalità efficiente di ricerca dei possibili valori.

    Ci sono casi in cui è preferibile ottenere lo stesso comportamento usando una datamap basata su documenti, ad esempio quando si sta sviluppando un’applicazione locale basata sulla Document Orientation Remota, come illustrato nel libro relativo alla Sincronizzazione.

    Per ottenere lo stesso comportamento del caso precedente usando i documenti, si inizia specificando il documento da selezionare nella proprietà Tipo contenuto della datamap. Siccome le datamap basate su documenti non hanno una query in cui inserire clausole where, al loro posto occorre scrivere la seguente riga nell’evento onLoad della videata:

    $vlSupplier.addDOFilter("SupplierID", $autocomplete, "value");

    Il metodo addDOFilter aggiunge un criterio di filtro alla datamap basata su documenti, specificando che il valore del filtro deve essere dinamicamente reperito dalla proprietà value dell’elemento $autocomplete. Così la datamap si comporta come nel caso precedente.

    Una seconda modifica riguarda le proprietà del documento contenute nella cartella Properties nella datamap: siccome essa è basata su un documento, la cartella ne contiene tutte le proprietà. È importante eliminare tutte le proprietà a parte quella che fornisce il valore all’autocomplete, in questo caso SupplierID, e quella che deve essere usata come decodifica, in questo caso CompanyName. La datamap, infatti, utilizza questi riferimenti per scegliere quali dati comunicare all’autocomplete. 

    Anche in questo caso è possibile aggiungere alla datamap diversi filtri, sia verso altri elementi che verso proprietà della videata, chiamando più volte il metodo addDOFilter.

    Selezione di dati provenienti da altre tabelle in layout lista #

    Le stesse tecniche viste finora per una videata di dettaglio possono essere utilizzate anche quando il controllo IonAutoComplete è contenuto in una lista. L’unica differenza è che se la datamap è basata su una query, la clausola where non può referenziare direttamente $autocomplete perché tutte le righe punterebbero sempre allo stesso elemento, cioè quello del template. Al posto di $autocomplete.value è possibile scrivere this.parentElement.value, dove this è la datamap e la proprietà parentElement si riferisce all’elemento che la contiene. In questo modo la datamap di ogni riga punta al proprio elemento. 

    Se la datamap è basata su documenti, la modifica riguarda la riga di codice da inserire nell’evento onLoad che diventa:

    $vlSupplier.addDOFilter("SupplierID", $vlSupplier.parentElement, "value");
    Ti è stato utile?
    Aggiornato il 15 Aprile 2024
    Creazione di liste di documentiDatamap innestate e ricorsive
    Contenuti
    • Gestione delle modifiche pendenti
    • Gestione dello stato dei pulsanti dell’intestazione
    • Selezione di dati provenienti da altre tabelle
      • Uso di controlli di tipo autocomplete
      • Uso di datamap basate su documenti e controlli di tipo autocomplete
      • Selezione di dati provenienti da altre tabelle in layout lista

    Caratteristiche

    • Perché Instant Developer
    • IDE e Ambiente di Sviluppo
    • Pubblicazione Web & Mobile
    • Software Life Cycle & DevOps
    • Database, Integrazione, Sync
    • Collaboration & Workflow

    Soluzioni

    • Freelance
    • Software House
    • Company IT
    • Casi di successo
    • Applicazioni Sviluppate

    Azienda

    • Chi Siamo
    • Contatti
    • Lavora con noi

    Risorse

    • Documentazione
    • Risorse e Tutorial
    • Blog
    • Starter Kit
    • Pricing
    • Inizia Ora
    Crea un account e Inizia Gratis
    • Seguici su Twitter
    • Seguici su Facebook
    • Seguici su LinkedIn
    • Seguici su YoutTubeSeguici su YouTube
    Questo sito è protetto dalla tecnologia reCAPTCHA Enterprise e si applicano l'Informativa sulla privacy e i Termini di servizio di Google.
    Google Policy | Termini
    © Pro Gamma - p.iva, c.f. e iscr. Camera di Commercio Bologna 01985091204 - Sede legale Via D'Azeglio, 51 40123 Bologna - Italia Pro Gamma Instant Developer® è un marchio registrato.
    Privacy Policy | Cookie Policy
    • IT