2015-12-15 4 views
13

Come accedere ad altre visualizzazioni secondarie nello stesso stato. Sto costruendo una pagina con una barra degli strumenti in alto e una barra laterale e voglio un pulsante sulla barra degli strumenti per aprire/chiudere la barra laterale ei pulsanti nella barra laterale per modificare il contenuto. facile è tutto nello stesso controller, ma quello che ho fatto è quello di utilizzare la funzione di visualizzazione secondaria di ui-router come questo:Ui-router angolare che passa i dati tra le sottoview dello stesso stato

.state('dash', { 
    url: '/dash/:id', 
    views: { 
     nav: { 
     controller: 'NavCtrl', 
     controllerAs: 'ctrl', 
     templateUrl: '/views/navbar.html' 
     }, 
     sidebar: { 
     controller: 'SidebarCtrl', 
     controllerAs: 'ctrl', 
     templateUrl: '/views/sidebar.html' 
     }, 
     content: { 
     controller: 'DashCtrl', 
     controllerAs: 'ctrl', 
     templateUrl: '/views/dash.html' 
     } 
    } 
    }) 

interfaccia utente è simile al seguente:

enter image description here

+0

se si denominano i controller in modo diverso con controller come, è possibile utilizzare il NavCtrl nel modello di sidebarCtrl. Forse usi un valore booleano che esiste sul NavCtrl, che decide cosa mostrare nella barra laterale? – Gustav

risposta

10

Definire una risoluzione e utilizzarla come posizione per memorizzare i dati comuni per lo stato del "trattino" attivato.

app.config(function($stateProvider) { 
    $stateProvider.state('dash', { 
    url: '/', 
    resolve: { 
     dashData: function() { 
     return { input: "default value" }; 
     } 
    }, 
    views: { 
     nav: { 
     controller: function() { 

     }, 
     controllerAs: 'ctrl', 
     template: '<h3>This is the Navbar</h3>' 
     }, 
     sidebar: { 
     controller: function(dashData) { // Inject reference to resolve object 
      this.dashData = dashData; 
     }, 
     controllerAs: 'ctrl', 
     template: 'content data visible in ' + 
        'the sidebar: <b>{{ ctrl.dashData.input }}<b>' 
     }, 
     content: { 
     controller: function(dashData) { // Inject reference to resolve object 
      this.dashData = dashData; 
     }, 
     controllerAs: 'ctrl', 
     template: '<input type="text" ng-model="ctrl.dashData.input">' + 
        'This is bound to dashData.input' 
     } 
    } 
    }) 
}); 

Iniettare l'oggetto condiviso in ogni controller

app.controller('DashCtrl', function(dashData, $scope) { 
    $scope.dashData = dashData; 
}); 
app.controller('... .... 

ho messo questo esempio in un plunker per voi: http://plnkr.co/edit/8M1zXN0W5ybiB8KyxvqW?p=preview

+0

Non sapevo di poter passare i dati per risolvere e leggerlo dalla risoluzione. State cercando di capire come ottenere risultati. Ti dispiace espandere un po 'la tua idea? – Mika

+0

Ho aggiornato la risposta, mostrando come passare la risoluzione, collegarla a più controller di vista figlio e aggiornare/mostrare i dati associati nelle viste. –

+0

Penso che questo (o I) manchi ancora qualcosa '' updates '$ scope.dashData' non è la variabile condivisa. – Mika

1

se si desidera il nome del tuo controller in modo diverso con controller come, è possibile utilizzare il NavCtrl nel modello di sidebarCtrl. Forse usi un valore booleano che esiste sul NavCtrl, che decide cosa mostrare nella barra laterale? (dal commento)

Questo dovrebbe funzionare, non l'ho provato però.

.state('dash', { 
     url: '/dash/:id', 
     views: { 
      nav: { 
      controller: 'NavCtrl', 
      controllerAs: 'navCtrl', 
      templateUrl: '/views/navbar.html' 
      }, 
      sidebar: { 
      controller: 'SidebarCtrl', 
      controllerAs: 'sidebarCtrl', 
      templateUrl: '/views/sidebar.html' 
      }, 
      content: { 
      controller: 'DashCtrl', 
      controllerAs: 'dashCtrl', 
      templateUrl: '/views/dash.html' 
      } 
     } 
     }) 

sidebarService:

angular.module('app').value('sidebarService', {show: true}); 

navCtrl qualcosa di simile:

function(sidebarService){ 
    var vm = this; 
    vm.toggleSideBar = function(){sidebarService.show = !sidebarService.show;}//used in navbar.html 
} 

sidebarCtrl:

function(sidebarService){ 
    var vm = this; 
    vm.showSideBar= sidebarService; 
} 

e poi in sidebar.html si utilizza il servizio a valore barra laterale:

<div ng-if="sidebarCtrl.showSideBar.show"> 
<!--SideBar--> 
</div 
+0

L'ho provato ma non riesco ad accedere ad altri controller dall'assenza di html corrispondente. In 'sidebar.html'' {{navCtrl.showSidebar}} 'non restituisce nulla. IDE dice "variabile navCtrl non risolto". – Mika

+0

sì, hai ragione. Forse perché sono ambiti di pari livello immagino ..., ma allora perché non usare qualche servizio di valore per archiviare il booleano? – Gustav

+0

Penso che non sia così pulito come trovare un buon modo per comunicare con i controller. – Mika

1

È possibile utilizzare gli eventi per la comunicazione tra controllori. Controllare la documentazione AngularJS per $scope.$broadcast e `$ portata $ su:. https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope

4

Questo sarebbe un buon esempio di dove uno stato di genitore astratta viene in aiuto:

Uno stato astratto può avere stati secondari ma non possono attivarsi autonomamente. Uno stato 'astratto' è semplicemente uno stato a cui non è possibile passare. Viene attivato implicitamente quando uno dei suoi discendenti viene attivato.

https://github.com/angular-ui/ui-router/wiki/Nested-States-and-Nested-Views#abstract-states

E poi soprattutto questo caso d'uso:

ereditare $ portata oggetti verso il basso per i bambini

Si consideri il seguente stato genitore astratta ed è stato bambino:

$stateProvider.state('root', { 
    abstract: true, 
    url: '/dash', 
    templateUrl: 'root.html', 
    controller: 'rootController' 
}); 

$stateProvider.state('dash', { 
    parent: 'root', 
    url: '/:id', 
    views: { 
     'navbar': { 
      templateUrl: 'navbar.html', 
      controller: 'navbarController' 
     }, 
     'sidebar': { 
      templateUrl: 'sidebar.html', 
      controller: 'sidebarController' 
     }, 
     'content': { 
      templateUrl: 'content.html', 
      controller: 'contentController' 
     } 
    } 
}); 

Ora è possibile archiviare la logica (e dati) avete bisogno nel vostro childstate nel controller dell'abstract Stato genitore:

angular.module('app').controller('rootController', [ 
      '$scope', 
    function ($scope) { 
     $scope.sidebar = { 
      show: true 
     }; 
     $scope.items = [{ 
      name: 'Alpha' 
     }, { 
      name: 'Bravo' 
     },{ 
      name: 'Charlie' 
     },{ 
      name: 'Delta' 
     }]; 
     $scope.selected = $scope.items[0]; 
     $scope.select = function (item) { 
      $scope.selected = item; 
     } 
    } 
]); 

Esempio di utilizzo di questa logica/dati in un modello dello stato del bambino, sidebar.html :

<ul class="nav nav-pills nav-stacked"> 
    <li ng-repeat="item in items" role="presentation"> 
     <a href="#" ng-click="select(item)">{{item.name}}</a> 
    </li> 
</ul> 

Ecco un esempio completo con le vostre esigenze, ho potuto inviare tutto il codice qui, ma penso che sarebbe un po 'troppo:

http://embed.plnkr.co/2jKJtFM0GWsylyLcAdne/

Sarò lieto di rispondere a qualsiasi domanda tu possa avere, basta gridare. In bocca al lupo!

+0

Grazie per la risposta. Penso che seguirò il tuo consiglio e userò uno stato astratto, ma ho assegnato la taglia Chris perché in realtà risponde alla domanda senza cambiamenti strutturali. – Mika