2013-07-23 10 views
29

W tej chwili mam aplikację, która ma pasek boczny, a pasek boczny ładuje różne szablony html przy użyciu ng-include w zależności od tego, jaką operację użytkownik wybierze. Jest to mapa związane app, tak na przykład, jeśli użytkownik wybierze przycisk „Dodaj Leg” będzie załadować szablon add_leg.html na pasku bocznym przy użyciu ng-include:Dynamicznie ładowane kontrolery i 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> 

To jest wszystko dobrze i działa zgodnie z oczekiwaniami, ale w tej chwili moja aplikacja używa tylko jednego kontrolera (MainCtrl w js/controllers.js) i zaczyna być naprawdę zagracona. Mam teraz wiele metod, ponieważ funkcjonalność aplikacji się rozszerza. Chciałbym podzielić mój kontroler na wiele kontrolerów jednocześnie zachowując funkcjonalność paska bocznego.

Chcę mieć MainCtrl jako główny kontroler, który kontroluje ładowanie szablonu paska bocznego (zmieniając zmienną sidebar_template wskazującą miejsce docelowe pliku) i chcę, aby kontrolowała niektóre z metod związanych z mapami globalnymi (np. pobieranie nazw przedmieść ze współrzędnych, itp.).

Próbowałam podzielić ją tak:

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

chcę LegCtrl i RouteCtrl odziedziczyć MainCtrl więc mogę uzyskać dostęp do jego zakresu i metod, to wszystko w porządku. Ale teraz problem polega na tym, jak dynamicznie ładować kontroler na pasek podziału paska bocznego w zależności od wymaganej funkcjonalności. Oryginalnie wszystkie moje metody były w MainCtrl, a to na opakowaniu div, który otacza div paska bocznego (patrz wyżej na przykład), więc nie było problemu.

Na przykład, powiedzmy naciśnięciu przycisku „Dodaj Leg”, to będzie trzeba zadzwonić addLeg w LegCtrl, ale LegCtrl nie jest załadowany w aplikacji, więc nie ma dostępu do tej metody. Mogę przechowywać addLeg() wewnątrz i zmienić tę zmienną na sidebar_template, aby załadować szablon, ale nic w szablonie nie zadziała, ponieważ teraz wywołuje metody z wnętrza LegCtrl.

muszę jakoś dynamicznie ładować kontroler na pasku bocznym w ng-include div, coś takiego może:

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

W nieprodukcyjnym powyższym przykładzie widać możliwe rozwiązanie myślałem o, ale Potrzebuję LegCtrl, aby być rzeczywistą funkcją kontrolera, a nie obiektu (aby działał ng-controller). Potrzebuję również sposób na wywołanie addLeg na LegCtrl z MainCtrl.addLeg (być może za pomocą transmisji?).

Jeśli ktokolwiek może wskazać mi właściwy kierunek, to byłoby wspaniale. Przepraszam za ogromny post, ale trzeba trochę wyjaśnić, żeby był spójny. Mam nadzieję, że ma to sens. Dzięki.

Aktualizacja: Chyba znalazłem rozwiązanie używając usługę działać jako kontrolę nawigacji (będzie ładować odpowiednich szablonów i nadawane zdarzenie do nowego kontrolera są załadowane dynamicznie, aby poinformować go, co do wykonywania funkcji):

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

Właśnie próbuje przetestować ten pomysł się teraz, ale transmisja .on nie działa.Myślę, że dzieje się tak dlatego, że emisja jest uruchamiana przed załadowaniem szablonu. Jak mogę to naprawić? Czy to dobre rozwiązanie dla tego, co robię?

+0

Widziałem twój plunker i edytowałem go, aby dołączyć do wiadomości konsoli. Pokaże ci, że wydarzenie jest publikowane jako pierwsze, a następnie słuchacz zaczyna nasłuchiwać. Dzieje się tak, ponieważ wszystko jest leniwie załadowane w kanciastej aplikacji. http://plnkr.co/edit/rWZ3x2Jzk9EV3OpD1HF1?p=preview –

Odpowiedz

12

Jeśli dobrze zrozumiałem, co można spróbować, należy utworzyć widok szablonu specjalnie w celu utworzenia nowej nogi.

Z głównego kontrolera wdrożyć niektóre logiki pokazać szablonowi

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

AddLeg szablon widoku byłoby załadować sterownika i tym samym zapewnić mechanizm rzeczywiście dodać nową nogę. Szablon będzie wyglądał tak, jak szablon:

Możesz dołączyć ten szablon do głównego html, używając ng-if + ng-include.

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

Zasadniczo można utworzyć wiele widoków i powiązać z tym samym kontrolerem (ale instancja będzie się różnić). W takim przypadku LegsController można powiązać z wieloma widokami w celu zapewnienia pełnej funkcjonalności.

+0

Problem polega na tym, że ładuję nowe szablony związane z funkcjonalnością nóg (np. może na szablonie addLeg jest przycisk do załadowania szablonu editLeg), przełączają szablony, będą miały własną definicję kontrolera w nowym kontrolerze (a tym samym stracą zasięg, a wszystkie zmienne stanowe zostaną utracone). – andro1d

+0

Możesz udostępnić model, utrzymując go poza kontrolerami i przekazując go jako część ng-init. – Chandermani

+0

hej Chandermani, czy możesz przejrzeć moją aktualizację? Dzięki. – andro1d

4

Mam rozwidlone swoje demo plunkr do jednego, że wierzę robi to, czego szukasz: http://plnkr.co/edit/whsjBT?p=preview

Świadczy to zdarzenie nadawany z jednego sterownika do drugiego po 2. sterownika (w naszym przykładzie LegCtrl tutaj) jest ładowany przez ng-include i przekazuje dane.

Użyłem zdarzenia od ng-include, aby opóźnić transmisję zdarzenia do momentu otrzymania raportów kątowych, że załadowano add_leg.html. Także myślę, że były pewne problemy z jak uzywasz $broadcast() ... to pierwszy parametr powinien być taki sam jak ten używany w $on() w LegCtrl

inny pomysł do rozważenia jest po prostu za pomocą samej usługi Navigation podzielić między państwa kontrolerów, jeśli jest to odpowiednie w twoim scenariuszu.

+0

To było dokładnie to, czego szukałem. Wielkie dzięki! –

5

Lubię te dane napędzany scenariusz, po prostu manipulować wierszy w szablonach:

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

i znaczników:

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

Aby dodać lub usunąć widoki, wystarczy zmodyfikować ET szablony voila! Jeśli potrzebujesz więcej kodu kontrolera, możesz dołączyć link do skryptu w załączniku. Sądzę, że mogą wystąpić komplikacje związane z wiązaniem danych w częściowym widoku, ale kompilacja $ powinna je rozwiązać.

Powiązane problemy