Realizzare un menu collassabile su una applicazione Instant Developer Cloud

Se volessi realizzare un menu di una applicazione web con più gruppi collassabili e magari a due livelli potrei fare come nell’esempio menu-collassabile presente nella Console di Instant Developer Cloud.

Il menu è quello classico dell’interfaccia IonicUI utilizzando una view che eredita da Ionic.MainPage e quello che vogliamo realizzare è questo (dove il menu è tutto espanso).

Come si può vedere abbiamo tre livelli principali:

  • Configurazione
  • Anagrafiche
  • Movimenti

Il menu Movimenti è a sua volta diviso in due sottomenu:

  • Contabili
  • Vendite

In alto abbiamo un oggetto IonToolbar che ha al suo interno un IonButton per espandere o collassare tutto il menu.

L’elemento btnEspandiCollassa ha l’icona arrow-dropdown che al click viene sostituita con arrow-dropup.

Il codice di onClick:

  $btnEspandiCollassa.icon = ($btnEspandiCollassa.icon === "arrow-dropdown") ? "arrow-dropup" : "arrow-dropdown";
  view.espandeCollassaMenu();

Il metodo view.espandeCollassaMenu toglie o aggiunge la classe css expanded ai gruppi di voci menu e imposta la giusta icona.

  $listVociConfiguazione.toggleClass("expanded");
  $listVociAnagrafiche.toggleClass("expanded");
  $listMovContabili.toggleClass("expanded");
  $listVociMovContabili.toggleClass("expanded");
  $listMovVendite.toggleClass("expanded");
  $listVociMovVendite.toggleClass("expanded");
  $iconConfigurazione.icon = ($iconConfigurazione.icon === "arrow-dropdown") ? "arrow-dropup" : "arrow-dropdown";
  $iconAnagrafiche.icon = ($iconAnagrafiche.icon === "arrow-dropdown") ? "arrow-dropup" : "arrow-dropdown";
  $iconMovimenti.icon = ($iconMovimenti.icon === "arrow-dropdown") ? "arrow-dropup" : "arrow-dropdown";
  $iconMovContabili.icon = ($iconMovContabili.icon === "arrow-dropdown") ? "arrow-dropup" : "arrow-dropdown";
  $iconMovVendite.icon = ($iconMovVendite.icon === "arrow-dropdown") ? "arrow-dropup" : "arrow-dropdown";

Analizziamo ora il menu vero e proprio che vediamo è fatto così:

C’è un primo IonList (listConfigurazione) che contiene la label Configurazione e su questo si applica il click per espandere o collassare quella voce.
Dopo qbbiamo un altro IonList (listVociConfigurazione) che contiene tutte le voci che richiamano videata.
Il click su Configurazione esegue questo codice:

  $listVociConfiguazione.toggleClass("expanded");
  $iconConfigurazione.icon = ($iconConfigurazione.icon === "arrow-dropdown") ? "arrow-dropup" : "arrow-dropdown";

Dove si aggiunge o toglie la classe css “expanded” e si imposta la giusta icona.

Il menu Movimenti che ha più livelli utilizza un Container per contenere l’ulteriore lista di elementi:

Per fare in modo che a design time gli elementi del menu si vedano tutti gli IonList che contengono voci di menu hanno le classi css menu ed expanded.
Poi nell’evento di load del mostro MainPage richiamiamo view.espandeCollassaMenu che compatta tutto.

Questo il css dell’applicazione:

.menu-list {
  margin-bottom: 0px !important;
}

.menu-leve0 {
  font-weight: bold;
}
/* Qui abbiamo anche l'animazione sul clic del menu che si collassa o espande */
.menu { 
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-height 0.3s ease, opacity 0.3s ease;
  padding-left: 15px;
  margin-bottom: 0px;
}

.menu.expanded {
  max-height: 100%;
  opacity: 1;
}

ion-list.menu-list > button.item,
ion-list.menu.expanded > button.item,
div.menu.expanded > button.item {
  min-height: 26px;
}
/* compatta le voci di menu */
ion-list.menu-list > button.item > .item-inner,
ion-list.menu.expanded > button.item > .item-inner,
div.menu.expanded > button.item > .item-inner {
  height: 26px;
}

ion-list.menu.expanded > button.item > .item-icon {
  margin-top: 0px;
  margin-bottom: 0px;
}

Non voglio spiegarvi proprio tutto ma potete guardare il progetto che è pubblico e del quale potete fare un fork, lo trovate nel workspace del vostro user personale nella sezione Progetti pubblici (occorre cercarlo per nome).

Naturalmente tutte le modifiche per migliorare l’esempio sono le benvenute :grinning:

P.S. Grazie a @a.marino e @d.pierangeli per l’aiuto a realizzare l’esempio.

2 Mi Piace