2014-07-15 10 views
24

Desidero specificare un controller in modo dinamico in base a una configurazione che viene caricata. Qualcosa di simile:Nome Dynamic NG-Controller

<div ng-controller="{{config.controllerNameString}}> 
    ... 
</div> 

Come si fa in modo angolare? Ho pensato che sarebbe stato molto facile, ma posso sembrare trovare un modo per farlo.

+0

C'è un controller genitore o è questo il controller più in alto? – tymeJV

+2

numerosi modi per caricare i modelli in base alle condizioni e avere il controller impostato nei modelli – charlietfl

+0

Questo avrebbe un controller principale. – RonSper

risposta

30

Quello che si desidera è eseguire un'altra istruzione prima che venga chiamato qualsiasi altro, ottenere il nome del controller da qualche modello rimuovere la nuova direttiva e aggiungere la direttiva ng-controller, quindi ricompilare l'elemento.

che assomiglia a questo:

global.directive('dynamicCtrl', ['$compile', '$parse',function($compile, $parse) { 
    return { 
    restrict: 'A', 
    terminal: true, 
    priority: 100000, 
    link: function(scope, elem) { 
     var name = $parse(elem.attr('dynamic-ctrl'))(scope); 
     elem.removeAttr('dynamic-ctrl'); 
     elem.attr('ng-controller', name); 
     $compile(elem)(scope); 
    } 
    }; 
}]); 

allora si potrebbe utilizzare nel modello, in questo modo:

<div dynamic-ctrl="'blankCtrl'">{{tyler}}</div> 

con un controller simile a questo:

global.controller('blankCtrl',['$scope',function(tyler){ 
    tyler.tyler = 'tyler'; 
    tyler.tyler = 'chameleon'; 
}]); 

C'è probabilmente un modo per interpolare il valore ($interpolate) dello dynamic-ctrl anziché di ng ($parse), ma non riuscivo a farlo funzionare per qualche motivo.

+0

Grazie. Esattamente quello che stavo cercando. Nel mio caso volevo passare una variabile $ scope anziché una stringa. Quindi ho solo dovuto fare dynamic-ctrl = "myScopeVariable" – mlhuff12

+6

soluzione Nide. Tuttavia, suggerisco una priorità di 550 invece di 100000. In questo modo, la direttiva viene eseguita prima di ng-controller (priorità 600) ma AFTER ng-if (priorità 600). Altrimenti il ​​controllore viene inizializzato (durante la chiamata a $ compile (elem) (scope)) anche se l'elemento non è nella pagina (se ng-if è falso). Inoltre, è possibile accedere agli attributi dell'elemento utilizzando il parametro 'attrs' della funzione di collegamento per gestire il rivestimento del cammello (es .: attrs.dynamicCtrl). – Marc

5

lo sto usando in ng-repeat, quindi questo è migliorato il codice per i cicli e gli oggetti secondari:

Template:

<div class="col-xs6 col-sm-5 col-md-4 col-lg-3" ng-repeat="box in boxes"> 
<div ng-include src="'/assets/js/view/box_campaign.html'" ng-dynamic-controller="box.type"></div> 
</div> 

direttiva:

mainApp.directive('ngDynamicController', ['$compile', '$parse',function($compile, $parse) { 
    return { 
     scope: { 
      name: '=ngDynamicController' 
     }, 
     restrict: 'A', 
     terminal: true, 
     priority: 100000, 
     link: function(scope, elem, attrs) { 
      elem.attr('ng-controller', scope.name); 
      elem.removeAttr('ng-dynamic-controller'); 

      $compile(elem)(scope); 
     } 
    }; 
}]); 
+0

add: if (scope.src) elem.attr ('src', "'" + scope.src + "'"); per supportare ng-include –

+0

Stai includendo la factory '$ parse' ma non la stai usando. –

+0

qual è il posto da inserire: if (scope.src) elem.attr ('src', "'" + scope.src + "'"); ? – fancoolo

2

Personalmente il 2 le soluzioni attuali qui non hanno funzionato per me, dal momento che il nome del controller non sarebbe noto quando si compilava per la prima volta l'elemento, ma successivamente durante un altro ciclo di digestione. Quindi ho finito per usare:

myapp.directive('dynamicController', ['$controller', function($controller) { 
    return { 
    restrict: 'A', 
    scope: true, 
    link: function(scope, elem, attrs) { 
     attrs.$observe('dynamicController', function(name) { 
     if (name) { 
      elem.data('$Controller', $controller(name, { 
      $scope: scope, 
      $element: elem, 
      $attrs: attrs 
      })); 
     } 
     }); 
    } 
    }; 
}]);