2014-07-15 12 views
24

Chcę dynamicznie określać kontroler na podstawie konfiguracji, którą wczytujemy. Coś takiego:Dynamiczna nazwa kontrolera NG

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

Jak to zrobić w kanciastym? Myślałem, że to będzie bardzo łatwe, ale mogę znaleźć sposób na zrobienie tego.

+0

Czy istnieje kontroler nadrzędny lub czy jest to najbardziej kontroler najwyższy? – tymeJV

+2

liczne sposoby ładowania szablonów na podstawie warunków i ustawienia kontrolera w szablonach – charlietfl

+0

To byłby kontroler nadrzędny. – RonSper

Odpowiedz

30

To, co chcesz zrobić, to uruchomić inną dyrektywę, zanim cokolwiek innego zostanie wywołane, pobierz nazwę kontrolera z jakiegoś modelu, usuń nową dyrektywę i dodaj dyrektywę ng-controller, a następnie ponownie skompiluj element.

To wygląda następująco:

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); 
    } 
    }; 
}]); 

Następnie można używać go w szablonie tak:

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

z kontrolerem jak ten:

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

tam prawdopodobnie sposób interpolacji wartości ($interpolate) z dynamic-ctrl zamiast parsi ng it ($parse), ale nie mogłem go uruchomić z jakiegoś powodu.

+0

Dziękuję. Dokładnie to, czego szukałem. W moim przypadku chciałem przekazać zmienną $ scope zamiast ciągu. Potrzebowałem więc rozwiązania dynamicznego ctrl = "myScopeVariable" – mlhuff12

+6

Nide. Jednakże sugeruję priorytet 550 zamiast 100000. W ten sposób dyrektywa jest wykonywana przed ng-kontrolerem (priorytet 600), ale AFTER ng-if (priorytet 600). W przeciwnym razie kontroler zostanie zainicjowany (podczas wywołania do $ compile (elem) (scope)), nawet jeśli element nie znajduje się na stronie (jeśli ng-if jest fałszywe). Ponadto możesz uzyskać dostęp do atrybutów elementu za pomocą parametru attrs funkcji łącza do obsługi obudowy wielbłąda (np .: attrs.dynamicCtrl). – Marc

5

Używam go w NG-powtórzenia, więc to jest lepsze kodu do pętli i podrzędnych obiektów:

Szablon:

<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> 

dyrektywa:

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 + "'"); do obsługi ng-include –

+0

Dołączasz fabrykę '$ parse', ale jej nie używasz. –

+0

jakie jest miejsce do umieszczenia: if (scope.src) elem.attr ('src', "'" + scope.src + "'"); ? – fancoolo

2

Osobiście 2 obecne rozwiązania tutaj nie działały dla mnie, ponieważ nazwa kontrolera nie byłaby znana przy pierwszym kompilowaniu elementu, ale później podczas kolejnego cyklu trawienia. Dlatego użyłem:

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 
      })); 
     } 
     }); 
    } 
    }; 
}]); 
Powiązane problemy