Zakres  (Scope)

Zakres jest wiązaniem utworzonym pomiędzy widokiem HTML i przynależącym do tego widoku kodem Javascript. Wiązanie to opisane jest przez obiekt, do którego mamy dostęp po obu stronach tej relacji. Możemy więc zmieniać zawartość tego obiektu zarówno z poziomu HTML-a jak i z poziomu kodu Javascript. Zmiany wykonane po jednej stronie są automatycznie widoczne po stronie drugiej.

Zasadnicza różnica pomiędzy kodem HTML a Javascript polega na tym, że w Javascript odwołujemy się do własności poprzez użycie konwencji obiektowej, natomiast w HTML używamy bezpośrednio nazwy własności.

Javascript:
$scope.suggestedRoleName = 'ADMIN'
HTML:
<input type="submit" ... value="Change to {{suggestedRoleName}}" />

Zakres główny i zakresy podrzędne

Z pojęciem scope silnie związane jest pojęcie root scope, które oznacza główny zakres aplikacji. Każda aplikacja może mieć tylko i wyłącznie jeden root scope. Ten natomiast może mieć dowolną ilość zakresów podrzędnych. Tych może być całkiem sporo, ponieważ każdorazowe użycie dyrektywy ng-controller oraz ng-repeat doprowadza do stworzenia nowego zakresu. W przypadku zagnieżdżania komponentów, każdy nowy zakres staje się automatycznie podrzędny do zakresu komponentu położonego wyżej:
<body ng-controller="AppCtrl">
    <div ng-controller="ParentCtrl">
        <div ng-controller="FirstChildCtrl">
        </div>
        <div ng-controller="SecondChildCtrl">
        </div>    
    </div>
</body>
W powyższym listingu możemy zaobserwować cztery różne kontrolery:
AppCtrl - kontroler, dla którego stworzony jest zakres główny (root scope)

ParentCtrl - kontroler, dla którego stworzony jest zakres podrzędny (scope)

FirstChildCtrl - kontroler, dla którego stworzony jest kolejny (nowy) zakres podrzędny (scope)

SecondChildCtrl - kontroler, dla którego stworzony jest jeszcze kolejny (kolejny nowy) zakres podrzędny (scope)
Istotne jest, że scope'y mogą dziedziczyć własności ze scope swojego rodzica, ale tak się dzieje tylko w przypadku zakresów o typie dziecka ("child scopes"). Istnieją bowiem jeszcze zakresy wyizolowane ("isolated scopes") i one nie potrafią dziedziczyć własności. Ten typ występuje w ramach dyrektyw, od których oczekujemy tego żeby były odseparowane od zakresu swojego rodzica. Więcej na ten temat piszemy w rozdziale: Dyrektywy własne, w paragrafie "Zakres dyrektyw".

Kontrolery a ich zakresy

Wracając do tematu relacji nawiązywanej między kontrolerem a zakresem, trzeba wspomnieć jeszcze o tym jaka jest ich interakcja:
  • Kontroler może poprzez zmianę scope'a wpływać na zmianę wartości modelu.

    Javascript:
    $scope.appa.timeFrom = new Date($scope.getTime(9));
    
    HTML:
    <input type="text"
        ...
        ng-model="appa.timeFrom"
        ng-click="openTimeFrom()"
        datetime-picker="HH:mm"
        timepicker-options="{'readonlyInput': true, 'showMeridian': false, 'minuteStep': 15}"
        ... 
    />
    
  • Kontroler wykorzystuje scope do tego by wyeksponować swoje funkcje, dzięki czemu stają się one widzialne dla widoku (w HTML), który w konsekwencji tego może je uruchomić.

    Javascript:
    $scope.openTimeFrom = function() {
        ...
    };
    
    HTML:
    <input type="text"
        ...
        ng-model="appa.timeFrom"
        ng-click="openTimeFrom()"
        datetime-picker="HH:mm"
        timepicker-options="{'readonlyInput': true, 'showMeridian': false, 'minuteStep': 15}"
        ... 
    />
    
  • Kontroler może rejestrować elementy obserwujące (watches) zmiany w modelu, które są uruchamiane automatycznie po każdej jego zmianie.

    Javascript:
    $scope.$watch('appa.timeFrom', function() {
        ...
    }, true);
    
    HTML:
    <input type="text"
        ...
        ng-model="appa.timeFrom"
        ng-click="openTimeFrom()"
        datetime-picker="HH:mm"
        timepicker-options="{'readonlyInput': true, 'showMeridian': false, 'minuteStep': 15}"
        ... 
    />
    
W zasadzie to tyle z tematów, które chcieliśmy poruszyć w tym rozdziale. Jeśli interesuje Was więcej detali to zapraszamy do sekcji linków na dole strony. Załączyliśmy tam odnośnik do oryginalnej dokumentacji AngularJS, do paragrafu opisującego zakresy.
Rekomendacja
Naprawdę bardzo mocno polecamy pobranie darmowego projektu dostępnego na naszym blogu pod linkiem Projekt startowy Spring Boot + AngularJS. Będzie on doskonałym uzupełnieniem wiedzy zdobytej w tym paragrafie.

Korzystając ze scopów należy pamiętać, aby unikać nadmiernego używania własności scopów nadrzędnych z poziomu scopów podrzędnych, gdyż może to z czasem doprowadzić do zmniejszenia czytelności kodu oraz powodować nieoczekiwane zachowanie komponentów po ich ewentualnej zmianie w przyszłości. Starajmy się zawsze trzymać nasze zmiany w obrębie zakresu dedykowanego kontrolerowi, w którym sie znajdujemy.

Mimo, że w kontrolerach mamy bezpośredni dostęp do zakresu głównego (poprzez wstrzyknięcie obiektu $rootScope), to tutaj również starajmy się korzystać z tego z umiarem. Zdecydowana większość funkcjonalności związanych bezpośrednio z danym komponentem powinna być obsługiwana w ramach jego scope'a.

Regularne ustawianie różnych własności z różnych kontrolerów z czasem doprowadzi do niezłego bałaganu w kodzie, który trudno będzie posprzątać. W takiej sytuacji po prostu nie wiadomo skąd i dlaczego dana wartość nagle uległa zmianie.
Używamy w StartAPPa


Oczywiście wszędzie w aplikacji korzystamy z zakresów. Niemniej fragmenty kodu, które posłużyły nam w tym rozdziale za przykład (oparte o komponentem daty) pochodzą konkretnie z modułu Formularz Zaawansowany. W pełnej wersji kod przedstawionych przykładów jest dużo bardziej rozbudowany i zawiera dodatkowo obsługę pozostałych komponentów. Mowa tutaj o komponentach typu select, checkbox, radio i wielu innych, których działanie możecie zobserwować po zalogowaniu się do aplikacji StartAPPa i wybraniu sekcji Formularz Zaawansowany.
Linki:
https://docs.angularjs.org/guide/scope

Stale się rozwijamy, a więc bądź na bieżąco!
Na ten adres będziemy przesyłać informacje o ważniejszych aktualizacjach, a także o nowych materiałach pojawiających się na stronie.
Polub nas na Facebooku:
Nasi partnerzy: stackshare
Javappa to również profesjonalne usługi programistyczne oparte o technologie JAVA. Jeśli chesz nawiązać z nami kontakt w celu uzyskania doradztwa bądź stworzenia aplikacji webowej powinieneś poznać nasze doświadczenia.
Kliknij O nas .


Pozycjonowanie stron: Grupa TENSE