2016-04-19 4 views
6

Sto provando a creare uno stato che si comporta come un popup, ovvero non cancella lo stato corrente, si apre semplicemente su di esso senza distruggere completamente lo stato corrente (So che l'utente può accedervi chiudendo il popup).Creazione di un popup come stato utilizzando l'ui-router AngularJS

fortemente semplificate, i miei percorsi Applications è qualcosa di simile al seguente:

angular.module('test', ['ui.router']) 
 
    .config(['$stateProvider', '$urlRouterProvider', 
 
    function($stateProvider, $urlRouterProvider) { 
 
     $stateProvider 
 
     .state('login', { 
 
      url: '/login', 
 
      template: '<button><a ui-sref="authenticated.home">Login</a></button>' 
 
     }) 
 
     .state('authenticated', { 
 
      url: '/authenticated', 
 
      template: '<p>We are now authenticated</p>' + 
 
      '<a ui-sref="authenticated.home">home</a>' + 
 
      '<a ui-sref="authenticated.statistics">statistics</a>' + 
 
      '<a ui-sref="authenticated.popup">Popup!</a>' + 
 
      '<div ui-view></div>' + 
 
      '<div ui-view="popup"></div>' 
 
     }) 
 
     .state('authenticated.home', { 
 
      url: '^/home', 
 
      template: '<p>We are in home. <br><input></p>' 
 
     }) 
 
     .state('authenticated.statistics', { 
 
      url: '^/statistics', 
 
      template: '<p>We are in statistics. <br><input></p>' 
 
     }) 
 
     .state('authenticated.popup', { 
 
      url: '^/popup', 
 
      views: { 
 
      popup: { 
 
       template: '<div id="popup"><p>popup is up</p>' + 
 
       '<a ui-sref="authenticated.home">close</a>' + 
 
       '</div>' 
 
      } 
 
      } 
 
     }); 
 
     $urlRouterProvider.otherwise('/login'); 
 
    } 
 
    ]);
a { 
 
    margin-right: 20px; 
 
    text-decoration: none; 
 
} 
 
#popup { 
 
    position: absolute; 
 
    top: 0; 
 
    bottom: 0; 
 
    width: 100%; 
 
    background: #000; 
 
    color: #fff; 
 
}
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.min.js"></script> 
 
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script> 
 
<div ng-app="test"> 
 
    <div ui-view> 
 
    </div> 
 
</div>

  • Utente è presentato con una schermata di login
  • volta effettuato l'accesso, l'utente viene reindirizzato a authenticated.home stato. Lo stato genitore autenticato contiene un menu di navigazione e <ui-view> per allegare subviews
  • L'utente può utilizzare questa navigazione per spostarsi all'interno dell'applicazione su altri percorsi come authenticated.statistics, authenticated.popup.

Il problema è che, quando ho semplicemente passare allo stato popup, anche se ho specificato popup vista dentro è vista oggetto, si cancella l'altro ui-view (ha un senso, però, perché non siamo più in una siamo stato che lo corrisponde).

Una soluzione che posso pensare è di utilizzare qualcosa come ui-router-extras per tornare allo stato precedente, il problema con questo è che tutte le modifiche che l'utente potrebbe aver fatto negli stati precedenti andranno perse.

Un'altra soluzione sarà avere il modello di popup nel modello di stato authenticated e mostrarlo/nasconderlo. Ma il problema con questo è che, il popup dovrebbe essere uno stato compatibile con i segnalibri, che carica i dati dal server in base ai parametri di stato.

C'è un approccio migliore per creare uno stato che si comporta come un popup sullo stato corrente? magari cambiando la struttura del template o usando qualcosa come abstract-states a cui non ho pensato?

+0

Qualsiasi motivo per cui [stati appiccicosi] (http://christopherthielen.github.io/ui-router-extras/#/sticky) da ui-router-extras ha vinto funziona? Hanno un [esempio qui] (http://plnkr.co/edit/qgt0RkEnXDPDTdMJPIfy?p=preview) e per quanto posso dire non c'è perdita di informazioni durante l'utilizzo del modale. –

+0

@AhmedWagdi Grazie, sembra promettente. Verificherò Forse puoi pubblicare una risposta –

risposta

2

suona come qualcosa che gli stati astratti potrebbero risolvere.

cambiando lo stato "autenticato" in un genitore astratto e collegando un controller ad esso può consentire di dati Axx trasformati da stati figlio. Inoltre, puoi semplicemente creare un controller separato per i tuoi dati e rilasciare un ng-controller sul body tag.

Se i probs stanno ancora implementando, come si usa LocalStorage per mantenere i dati desiderati?

Update2 Trovato un post e cambiato il plnk sul ng-modello di aggiornamento durante la digitazione, ma vedo il motivo per cui OP vuole un popup.

Modifica Plnkr Shared State Example

cercherò di trovare un buon esempio, ma ecco qualche pseudo codice per ora.

.state('authenticated', { 
     abstract: true, 
     url: '/authenticated', 
     controller: 'AuthStateController', 
     template: '<p>We are now authenticated</p>' + 
     '<a ui-sref="authenticated.home">home</a>' + 
     '<a ui-sref="authenticated.statistics">statistics</a>' + 
     '<a ui-sref="authenticated.popup">Popup!</a>' + 
     '<div ui-view></div>' + 
     '<div ui-view="popup"></div>' 
    }) 

Credo che con o senza {abstract: true} il tuo stato popup deve avere accesso ai dati all'interno di 'AuthStateController'. La soluzione potrebbe essere una soluzione di overkill, ma potrebbe darti un'idea di come utilizzare i dati dei controller in modo più efficiente .. se tutto il resto fallisce ... crea un servizio per gestire i dati.

.state('authenticated.popup', { 
     url: '^/popup', 
     views: { 
     popup: { 
      resolve: { 
      ctrl: 'AuthStateController', 
      data: function(ctrl) { 
       return ctrl.data_for_popup; 
      } 
      } 
      template: '<div id="popup"><p>popup is up</p>' + 
      '<a ui-sref="authenticated.home">close</a>' + 
      '</div>' 
     } 
     } 
    }) 
+0

* "cambiare lo stato" autenticato "in un genitore astratto e collegarlo ad un controller può permetterti di trasformare i dati di axx in stati figli" * - Non sono sicuro di cosa intendi con * " consenti ai dati axx "*. Potresti mostrare un esempio basato sulla demo in questione? Ho già controller per ogni stato. Il problema è che il controller viene reinizializzato quando torna a quello stato. E ho posto questa domanda per uno stato di "popup like" sperando di evitare di dover archiviare i dati io stesso –

+0

grazie per il suggerimento di fusione .. finché i dati necessari sono memorizzati in AuthStateController, sarà presente attraverso tutti gli stati figlio di " Ah ... " – 4UmNinja

+0

Ah ... vedo che stai suggerendo di avere un controller principale condiviso con tutti i dati per tutti gli stati figlio e usare l'ereditarietà prototipica ... Questa è una buona idea ma sfortunatamente gli stati figlio hanno i loro controllori e i propri dati inseriti dall'utente, prelevati dal server ecc. Questi dati non saranno presenti nel genitore condiviso:/ –

0

Probabilmente quello che stai cercando è diverso nella tua pagina principale. Devi mantenere 2 ui-view sul tuo index.html o sul tuo modello di base.

E poi durante il caricamento degli stati fare qualcosa di simile:

$stateProvider.state('stateNAme', { 
       url: '/name', 
       views: { 
        "main": { 
         controller: '1Controller', 
         templateUrl: 'tpl1.html' 
        }, 
        "[email protected]": { 
         controller: '2Controller', 
         templateUrl: 'tpl2.html' 
        } 
       } 

Leggi qui circa il multiplo chiamato views

+0

Come riuscirai a ottenere tutto quanto menzionato nella domanda ..?! Sto usando le viste nominate nella domanda stessa. –

4

La sticky states add on da ui-router-extras dovrebbe essere quello che stai cercando. Ti dà la possibilità di creare stati appiccicosi/paralleli quindi dovrebbe permetterti di creare uno stato popup senza alterare lo stato originale in cui ti trovavi.

Non ho sperimentato abbastanza con esso per conoscere tutti i dettagli ma l'idea principale è quello di spostare tutti voi gli stati principali in uno stato di radice app e impostare appiccicoso true:

$stateProvider.state('app', { 
     url: '', 
     views: { 
     'app': { 
      templateUrl: 'app.html', 
      controller: 'mainCtrl', 
     } 
     }, 
     sticky: true 
    }); 

    $stateProvider.state('app.account', { 
     url: '/account', 
     templateUrl: 'account.html' 
    }); 

    $stateProvider.state('app.account.stuff', { 
     url: '/stuff', 
     template: "<h3>Here's my stuff:</h3><ul><li>stuff 1</li><li>stuff 2</li><li>stuff 3</li></ul>" 
    }); 

Dopo di che aggiungere il vostro stato modale come un fratello (quindi non come un bambino dello stato radice app)

$stateProvider.state('modal', { 
     url: '/modal', 
     views: { 
     'modal': { 
      templateUrl: 'modal.html' 
     } 
     } 
    }); 

Ho preso l'esempio fornito nella documentazione e alcune modifiche per aggiungere controller e semplificarla: http://plnkr.co/edit/4JGdIcDUQs0Za4fBaLj1?p=preview