2013-05-02 14 views
38

Próbuję zaimplementować system wtyczek w angularjs, który umożliwi użytkownikom konfigurowanie "widżetów", które zobaczą na określonej stronie. Każdy widget jest definiowany przez kontroler i szablon (adres URL). Czy jest możliwe utworzenie dyrektywy, która tworzy instancję kontrolera, wywołuje ją za pomocą szablonu i transkoduje wynikową treść?Ręcznie sterowany kontroler AngularJS i szablon

Celem jest coś takiego:

<div class="widget" ng-repeat="widget in widgets"> 
    <widget controller="widget.controller" templateUrl="widget.templateUrl"></widget> 
</div> 
+1

Jest to w zasadzie to, co robi 'ngView'; chociaż twój przypadek użycia jest trochę prostszy, możesz znaleźć jego [kod źródłowy] (https://github.com/angular/angular.js/blob/master/src/ng/directive/ngView.js). Zasadniczo, pobierz, dołącz do DOM, a następnie '$ compile' swój szablon, a następnie przypisz kontroler:' element.children(). Data ('$ ngControllerController', kontroler); '. Jeśli będę miał czas później, opublikuję bardziej kompletną odpowiedź. –

Odpowiedz

72

Istnieją dwa sposoby, aby to zrobić; jeden korzysta z już dostępnych dyrektyw pomocniczych (takich jak ngInclude i ngController), a drugi jest ręczny; Ręczna wersja może być szybsza, ale nie mogę być tego pewna.

Easy Way:

Prosta metoda jest prosta utworzyć nowy element z ngController i ngInclude atrybutów, dołączyć go do elementu tej dyrektywy, a następnie $compile go:

var html = '<div ng-controller="'+ctrl+'" ng-include="'+tpl+'"></div>'; 
element.append(html); 
$compile(element.contents())(scope); 

Metoda ręczna:

Sposób ręczny polega na wykonaniu tych samych instrukcji. z kolei; ta logika jest bardzo podobna do tego, co robi ngView (choć bez złożoności). Pobieramy szablon, przechowując go w $templateCache, a następnie dołączamy do DOM. Tworzymy nowy zakres podrzędny i tworzymy instancję kontrolera i przypisujemy go do elementu. Wreszcie, $compile go:

$http.get(tpl, { cache: $templateCache }) 
.then(function(response) { 
    templateScope = scope.$new(); 
    templateCtrl = $controller(ctrl, { $scope: templateScope }); 
    element.html(response.data); 
    element.children().data('$ngControllerController', templateCtrl); 
    $compile(element.contents())(templateScope); 
}); 

(Zauważ, że nie ma garbage collection tutaj, które należy wdrożyć, jeśli widgety zmianie)

Oto Plunker wykazując obie metody: http://plnkr.co/edit/C7x9C5JgUuT1yk0mBUmE?p=preview

+0

To wygląda na świetne rozwiązanie, jest jasne i logiczne, problem z "łatwą drogą" polega na tym, że ng-include nie jest oceniany, ładuje kontroler :) – perrohunter

+1

Ta linia jest świetna: '$ http.get (tpl, {cache: $ templateCache}) . Then (funkcja (odpowiedź) {...) '. Dzięki! – SimplGy

+0

To nie działa dla mnie, chyba że zadzwonię do 'scope. $ Apply()' – Simone

Powiązane problemy