2013-07-23 17 views
29

Al momento ho un'app con una barra laterale e la barra laterale carica diversi modelli html utilizzando ng-include in base all'operazione che l'utente sceglie di eseguire. E 'una mappa legate app, così per esempio, se l'utente seleziona il pulsante 'Aggiungi Leg' sarà caricare il modello add_leg.html nella barra laterale utilizzando ng-include:Caricamento dinamico di controller e ng-include

// The Javascript code: 
$scope.addLeg = function() { 
    $scope.sidebar = true; 
    $scope.sidebar_template = '/partials/legs/add_leg.html';  
} 

// Simplified example of HTML: 
<html> 
<div ng-app="MyApp" ng-controller="MainCtrl"> 
    <a ng-click="addLeg()">Add Leg</a> 
    <a ng-click="addRoute()">Add Route</a> 
    <a ng-click="editLeg()">Edit Leg</a> 
    <a ng-click="editRoute()">Edit Route</a> 
    ... 

    <div id="sidebar" ng-class="{'sidebar-hidden': sidebar == false}"> 
     <div ng-include src="sidebar_template"></div> 
    </div> 

    <google-map></google-map> 
</div> 

Questo è tutto molto bello e funziona, se lo desideri, ma al momento la mia app utilizza solo un controller (MainCtrl in js/controllers.js) e sta iniziando a diventare davvero disordinato. Ora ho molti metodi perché la funzionalità delle app si sta espandendo. Mi piacerebbe dividere il controller in più controller mantenendo questa funzionalità della barra laterale.

Desidero avere il MainCtrl come controller principale che controlla il caricamento del modello della barra laterale (cambiando la variabile sidebar_template che punta alla destinazione del file) e voglio che controlli alcuni metodi della mappa globale (come recupero dei nomi dei sobborghi dalle coordinate, ecc.).

Ho cercato di dividere in questo modo:

controllers/js/main.js - MainCtrl 
controllers/js/legs.js - LegCtrl 
controllers/js/routes.js - RouteCtrl 

Voglio che il LegCtrl e RouteCtrl ereditare la MainCtrl modo che io possa accedere alla sua finalità e le modalità, che è tutto bene. Ma ora il problema è come caricare dinamicamente il controller sulla barra laterale div in base a quale funzionalità è richiesta. Originariamente tutti i miei metodi erano in MainCtrl, e questo è nel div del wrapper che circonda il div sidebar (vedi di nuovo sopra per un esempio), quindi non era un problema.

Ad esempio, dire premo il pulsante 'Aggiungi Leg', sta andando ad avere bisogno di chiamare in addLegLegCtrl, ma LegCtrl non viene caricata sul app, in modo da non avere accesso al metodo. Potrei conservare addLeg() all'interno dello MainCtrl e fare in modo che cambi la variabile sidebar_template per caricare il modello, ma nulla nel modello funzionerà perché chiama i metodi dall'interno dello LegCtrl ora.

ho bisogno di caricare qualche modo dinamico il controller ng-include div della barra laterale, qualcosa di simile, forse:

// MainCtrl 
$scope.addLeg = function() { 
    $scope.required_controller = LegCtrl; 

    $scope.sidebar = true; 
    $scope.sidebar_template = '/partials/legs/add_leg.html';  

    LegCtrl.addLeg(); 
} 

<div id="sidebar" ng-class="{'sidebar-hidden': sidebar == false}"> 
    <div ng-include src="sidebar_template" ng-controller="{{required_controller}}"></div> 
</div> 

Nell'esempio non funzionante sopra potete vedere una possibile soluzione che ho pensato, ma Ho bisogno di LegCtrl per essere la funzione effettiva del controller, non un oggetto (per il ng-controller funzionare). Ho anche bisogno di un modo per chiamare addLeg su LegCtrl da MainCtrl.addLeg (forse usando la trasmissione?).

Se qualcuno può indicarmi la giusta direzione sarebbe fantastico. Scusa per l'enorme post, aveva bisogno di un po 'di spiegazioni per renderlo coerente. Spero che abbia senso. Grazie.

Aggiornamento: Penso di aver trovato una soluzione utilizzando un servizio per agire come controllo di navigazione (caricherà i modelli rilevanti e trasmetterà un evento al nuovo controller che viene caricato dinamicamente per dirgli quale funzione eseguire):

http://plnkr.co/edit/Tjyn1OiVvToNntPBoH58?p=preview

Sto solo cercando di testare questa idea fuori ora, ma la trasmissione .on non funziona.Penso che sia perché la trasmissione si attiva prima del caricamento del modello. Come posso risolvere questo? Questa è una buona soluzione per quello che sto facendo?

+0

Ho visto il plunk e l'ho modificato per includerlo nei messaggi della console. Ti mostrerà che l'evento è pubblicato per primo e poi l'ascoltatore inizia ad ascoltare. Questo accade perché ogni cosa è pigra caricata nell'app angolare. http://plnkr.co/edit/rWZ3x2Jzk9EV3OpD1HF1?p=preview –

risposta

12

Se ho capito bene, ciò che è possibile provare è creare una vista modello per creare una nuova gamba.

Dal controller principale attuare una logica per mostrare il modello

$scope.addLeg=function() { 
    $scope.showAddLeg=true; 
} 

La vista modello AddLeg sarebbe caricare il controllore e quindi fornire un meccanismo per aggiungere effettivamente nuovo segmento. Il modello sarà simile

<script type="text/ng-template" class="template" id="addLegTemplate"> 
    <div ng-controller='LegsController'> 
    <!--html for adding a new leg--> 
    </div> 
</script> 

È possibile includere questo modello dentro di te html principale utilizzando ng-if + NG-includere.

<div ng-if='showAddLeg'><div ng-include='addLegTemplate'/></div> 

In pratica è possibile creare visualizzazione multipla e legarsi a stesso controller (ma esempio potrebbe essere diverso). In questo caso lo LegsController può essere associato a più viste per supportare la funzionalità completa.

+0

Il problema con questo è se sto caricando nuovi modelli relativi alla funzionalità della gamba (cioè forse sul modello addLeg è un pulsante per caricare il modello editLeg), quando cambiano i modelli avrà la propria definizione di controller nel nuovo controller (e quindi perderà l'ambito e tutte le variabili di stato andranno perse). – andro1d

+0

È possibile condividere il modello mantenendolo all'esterno dei controller e passandolo come parte di ng-init. – Chandermani

+0

hey Chandermani, puoi dare un'occhiata al mio aggiornamento? Grazie. – andro1d

4

ho biforcato tua plunkr demo in uno che credo fa quello che stai cercando: http://plnkr.co/edit/whsjBT?p=preview

Questo dimostra un evento in onda da un controller a un altro dopo il 2 ° controllore (LegCtrl nel nostro esempio qui) viene caricato tramite ng-include e passando i dati.

Ho utilizzato l'evento $includeContentLoaded da ng-include per ritardare la trasmissione dell'evento fino a quando i rapporti angolari non hanno caricato add_leg.html. Inoltre penso che ci sono stati alcuni problemi con il modo che si stava utilizzando $broadcast() ... è primo parametro dovrebbe essere la stessa di quella utilizzata in $on() in LegCtrl

Un'altra idea di prendere in considerazione è semplicemente usando il vostro servizio Navigation stesso per condividere lo stato tra i controller se questo è appropriato nel tuo scenario.

+0

Questo era esattamente quello che stavo cercando. Grazie mille! –

5

Mi piace questo scenario i dati driven, basta manipolare le righe nei modelli:

$scope.templates = [ 
    { name: 'include1.html', url: 'partials/include1.html' } 
]; 
$scope.addTemplate = function(name, url) { 
    $scope.templates.push({ name: name, url: url }); 
}; 

e la marcatura:

<div ng-repeat="template in templates" ng-include="template.url"></div> 

Per aggiungere o rimuovere viste, basta modificare i modelli et voilà! Se hai bisogno di più codice controller, puoi includere un link allo script nell'include. Immagino che ci possano essere delle complicazioni con l'associazione ai dati nella vista parziale stessa, ma $ compilare dovrebbe risolverli.

Problemi correlati