• 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

    ShadowUI

    • Introduzione ShadowUI
    • Progetti di esempio
    • Elementi disponibili
    • Installazione
    • Le pagine ShadowUI
    • La HeaderBar e il Breadcrumb
    • I pulsanti
    • Le tabbed view
    • Definire il contenuto delle pagine
    • Il page controller
    • Sidebar e Menu
    • Componenti Shadow UI
    • Template
    • Personalizzazione

    Pannelli Griglie e Alberi

    • Introduzione (Pannelli griglie e alberi)
    • Anatomia di un pannello
    • I pannelli a runtime
    • Anatomia di un albero
    • Gli alberi 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

    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

    Il page controller

    Table Of Contents
    • Metodi principali
      • Riepilogo metodi
    • Pattern avanzati
      • 1. Navigazione condizionale
      • 2. Navigazione con parametri complessi
      • 3. Stack profondo con breadcrumb
      • 4. Rimozione selettiva dallo stack
      • 5. Navigazione modale con popup
      • 6. Gestione stati back button
      • 7. Preload pagine successive
      • 8. Navigazione con transizioni personalizzate
      • 9. Comunicazione bidirezionale tra pagine
      • 10. Gestione errori navigazione
    • Ciclo di vita pagina

    Il page controller gestisce la navigazione e il ciclo di vita delle pagine nell’applicazione.

    Metodi principali #

    I metodi principali del page controller sono già stati descritti nel capitolo Il contenitore pagine (ShaNavController) nella sezione Navigazione: Proprietà e Metodi del Page Controller. Qui riassumiamo i concetti chiave e aggiungiamo pattern avanzati.

    Riepilogo metodi #

    MetodoDescrizione
    push(viewclass, options)Apri una nuova pagina
    pop(count, info)Torna indietro
    remove(count, info)Rimuovi pagine dallo stack
    toggleMenu(show)Apri/chiudi sidebar
    setTitle(title)Aggiorna titolo (solo Sticky)
    setBreadcrumb()Aggiorna breadcrumb
    getActivePage()Ottieni pagina attiva
    postMessage(msg)Invia messaggio alle pagine

    Pattern avanzati #

    1. Navigazione condizionale #

    function* openDetail() {
      // Controlla permessi prima di navigare
      let hasPermission = yield app.checkPermission("view_details");
    
      if (!hasPermission) {
        yield app.toast("Accesso negato", { variant: "destructive" });
        return;
      }
    
      yield view.push(App.DetailView, {
        title: "Dettaglio",
        itemId: this.itemId
      });
    }

    2. Navigazione con parametri complessi #

    function* openEditView() {
      yield view.push(App.EditView, {
        title: "Modifica Ticket",
        // Passa oggetto completo
        ticket: {
          id: this.ticket.id,
          title: this.ticket.title,
          status: this.ticket.status,
          assignee: this.ticket.assignee
        },
        // Callback per aggiornamento
        onSave: (updatedTicket) => {
          this.updateLocalTicket(updatedTicket);
        }
      });
    }
    
    // In EditView - onLoad
    function* onLoad() {
      let ticket = this.options.ticket;
    
      // Popola form
      this.view.titleInput.value = ticket.title;
      this.view.statusSelect.value = ticket.status;
    }
    
    // In EditView - save
    function* saveButton_onClick() {
      let updated = yield this.save();
    
      // Chiama callback se fornito
      if (this.options.onSave) {
        this.options.onSave(updated);
      }
    
      yield view.pop(1, { saved: true });
    }

    3. Stack profondo con breadcrumb #

    // Crea navigazione profonda mantenendo breadcrumb
    
    // 1. Dashboard (root)
    yield view.push(App.DashboardView, {
      root: true,
      title: "Dashboard"
    });
    
    // 2. Lista progetti
    yield view.push(App.ProjectsView, {
      title: "Progetti"
    });
    
    
    // 3. Dettaglio progetto
    yield view.push(App.ProjectDetailView, {
      title: "Progetto Alpha",
      projectId: 123
    });
    // Breadcrumb: Dashboard > Progetti > Progetto Alpha
    
    // 4. Lista task
    yield view.push(App.TasksView, {
      title: "Task",
      projectId: 123
    });
    // Breadcrumb: Dashboard > Progetti > Progetto Alpha > Task
    
    // 5. Dettaglio task
    yield view.push(App.TaskDetailView, {
      title: "Task #45",
      taskId: 45
    });
    // Breadcrumb: Dashboard > ... > Progetto Alpha > Task > Task #45

    4. Rimozione selettiva dallo stack #

    // Scenario: Dashboard → Projects → ProjectDetail → TaskList → TaskDetail
    // Vogliamo: Dashboard → ProjectDetail → TaskDetail
    // (rimuoviamo Projects e TaskList)
    
    function* saveTaskButton_onClick() {
      yield this.saveTask();
    
      // Rimuovi TaskList e Projects dallo stack
      yield view.remove(App.TasksView);
      yield view.remove(App.ProjectsView);
    
      // Ora lo stack è: Dashboard → ProjectDetail → TaskDetail
    
      yield app.toast("Task salvato", { variant: "success" });
    }

    5. Navigazione modale con popup #

    // Apri form come popup invece che pagina normale
    function* quickAddButton_onClick() {
      yield view.push(App.QuickAddView, {
        popup: true,
        title: "Aggiungi rapido",
        // Opzioni popup
        popupPosition: "center",
        popupWidth: "500px",
        backdrop: true
      });
    }
    
    // In QuickAddView - dopo salvataggio
    function* saveButton_onClick() {
      yield this.save();
    
      // Chiudi popup
      this.view.close();
    
      // Notifica pagina sottostante
      yield view.postMessage({
        type: "item-added",
        item: this.savedItem
      });
    }
    
    // In pagina principale - ricevi notifica
    function* onMessage(message) {
      if (message.type === "item-added") {
        // Ricarica lista
        yield this.view.itemsDM.load();
      }
    }

    6. Gestione stati back button #

    // Gestisci back button browser/Android
    function* canClose() {
      // Chiamato quando utente preme back
      let hasUnsavedChanges = this.checkUnsavedChanges();
    
      if (hasUnsavedChanges) {
        let confirm = yield app.popup(
          "Modifiche non salvate",
          "Vuoi salvare prima di uscire?",
          ["Annulla", "Esci senza salvare", "Salva ed esci"]
        );
    
        if (confirm === 0) {
          return false; // Blocca chiusura
        } else if (confirm === 2) {
          yield this.save();
        }
      }
      return true; // Permetti chiusura
    }

    7. Preload pagine successive #

    // Precarica dati della pagina successiva per transizioni veloci
    function* openDetailButton_onClick() {
      let itemId = this.selectedItem.id;
    
      // Avvia caricamento dati in background
      let dataPromise = app.api.getItemDetail(itemId);
    
      // Naviga immediatamente
      yield view.push(App.DetailView, {
        title: "Dettaglio",
        itemId: itemId,
        preloadedData: dataPromise  // Passa promise
      });
    }
    
    // In DetailView - onLoad
    function* onLoad() {
      if (this.options.preloadedData) {
        // Usa dati precaricati
        let data = yield this.options.preloadedData;
        this.populateView(data);
      } else {
        // Carica normalmente
        yield this.loadData();
      }
    }

    8. Navigazione con transizioni personalizzate #

    // Disabilita animazione per navigazione veloce
    yield view.push(App.TargetView, {
      title: "Target",
      animate: false  // Nessuna transizione
    });
    
    // Forza animazione anche se disabilitata globalmente
    yield view.push(App.TargetView, {
      title: "Target",
      animate: true
    });

    9. Comunicazione bidirezionale tra pagine #

    // Pagina A apre Pagina B e attende risultato
    
    // In PageA
    function* selectUserButton_onClick() {
      yield view.push(App.UserPickerView, {
        popup: true,
        title: "Seleziona Utente",
        currentUser: this.currentUser
      });
    }
    
    function* onMessage(message) {
      if (message.type === "user-selected") {
        // Ricevi utente selezionato
        this.view.userInput.value = message.user.name;
        this.selectedUser = message.user;
      }
    }
    
    // In UserPickerView
    function* userRow_onClick() {
      let user = this.sender.row;
    
      // Invia risultato a pagina chiamante
      yield view.postMessage({
        type: "user-selected",
        user: user
      });
    
      // Chiudi picker
      this.view.close();
    }

    10. Gestione errori navigazione #

    function* navigateToDetail() {
      try {
        let itemId = this.selectedItem.id;
    
        // Verifica esistenza item
        let exists = yield app.api.checkItemExists(itemId);
    
        if (!exists) {
          yield app.toast("Elemento non trovato", {
            variant: "destructive"
          });
          return;
        }
    
        // Naviga
        yield view.push(App.DetailView, {
          title: "Dettaglio",
          itemId: itemId
        });
    
      } catch (error) {
        yield app.toast(`Errore: ${error.message}`, {
          variant: "destructive"
        });
    
        console.error("Navigation error:", error);
      }
    }

    Ciclo di vita pagina #

    Eventi principali:

    1. Constructor: Creazione istanza
    2. onLoad(options): Caricamento iniziale
    3. onShow(): Pagina mostrata (anche dopo ritorno)
    4. onBack(closedView, info): Ricezione da pagina chiusa
    5. onMessage(message): Ricezione messaggi
    6. canClose(): Verifica prima di chiusura
    7. onClose(): Chiusura pagina

    Esempio completo:

    // In una view
    function* onLoad() {
      console.log("1. onLoad - caricamento iniziale");
    
      // Ricevi parametri
      this.itemId = this.options.itemId;
    
      // Carica dati
      yield this.loadData();
    }
    
    function* onShow() {
      console.log("2. onShow - pagina mostrata");
    
      // Aggiorna dati se necessario
      if (this.needsRefresh) {
        yield this.refresh();
        this.needsRefresh = false;
      }
    }
    
    function* onBack(closedView, info) {
      console.log("3. onBack - ritorno da altra pagina");
    
      // Ricevi dati da pagina chiusa
      if (info.saved) {
        yield this.refresh();
      }
    }
    
    function* onMessage(message) {
      console.log("4. onMessage - messaggio ricevuto");
    
      if (message.type === "data-changed") {
        this.needsRefresh = true;
      }
    }
    
    function* canClose() {
      console.log("5. canClose - verifica chiusura");
    
      // Verifica modifiche non salvate
      if (this.hasUnsavedChanges()) {
        let confirm = yield app.popup(
          "Conferma",
          "Ci sono modifiche non salvate. Continuare?",
          ["Annulla", "Esci"]
        );
    
        return (confirm === 1);
      }
    
      return true;
    }
    
    function* onClose() {
      console.log("6. onClose - chiusura pagina");
    
      // Cleanup risorse
      this.cleanup();
    }
    Ti è stato utile?
    Aggiornato il 10 Novembre 2025
    Definire il contenuto delle pagineSidebar e Menu
    Contenuti
    • Metodi principali
      • Riepilogo metodi
    • Pattern avanzati
      • 1. Navigazione condizionale
      • 2. Navigazione con parametri complessi
      • 3. Stack profondo con breadcrumb
      • 4. Rimozione selettiva dallo stack
      • 5. Navigazione modale con popup
      • 6. Gestione stati back button
      • 7. Preload pagine successive
      • 8. Navigazione con transizioni personalizzate
      • 9. Comunicazione bidirezionale tra pagine
      • 10. Gestione errori navigazione
    • Ciclo di vita pagina

    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