Czas na kolejny wpis z serii Angular Tips & Tricks! Tyle tytułem wstępu, ruszamy.
1. AbstractControl i metoda GET
Zdarza się, że model reaktywnego formularza posiada zagnieżdżone obiekty. W celu dobrania się do zagnieżdzonej kontrolki, często spotykam się z następującym, przykładowym kodem (najczęściej na widoku przy obsłudze errorów):
1 2 3 |
user: FormGroup; .... user.get('details').get('account').get('email') |
Powyższą formę, możemy zapisać również w skróconej formie:
1 |
user.get('details.account.email') |
2. Angular CLI i Autoprefixer
Wspierasz inne przeglądarki i pojawia się taki kod w Twoim projekcie?
1 2 3 4 5 |
example { -webkit-transform: rotate(30deg); /* Ch <36, Saf 5.1+, iOS < 9.2, An =<4.4.4 */ -ms-transform: rotate(30deg); /* IE 9 */ transform: rotate(30deg); /* IE 10, Fx 16+, Op 12.1+ */ } |
Jeśli tak, to jest to całkowicie zbędne. Wystarczy wyłącznie:
1 |
transform: rotate(30deg); |
Angular CLI posiada wbudowany Autoprefixer, który zadba o dodanie odpowiednich prefixów do styli. Możesz również sprecyzować, jakie przeglądarki chcesz wspierać. Więcej szczegółów:
https://github.com/angular/angular-cli/wiki/stories-autoprefixer
3. Obsługa subskrypcji
Warto wiedzieć, że biblioteka RxJS udostępnia nam metodę do dodawania subskrypcji. Jak przeglądam tutoriale / materiały z Angulara, to trafiam z reguły na taki kod:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
someSubscription1 : Subscription; someSubscription2 : Subscription; ngOnInit() { this.someSubscription1 = ...subscribe(...); this.someSubscription2 = ...subscribe(...); } ngOnDestroy() { if (this.someSubscription1) { this.someSubscription1.unsubscribe(); } if (this.someSubscription2) { this.someSubscription2.unsubscribe(); } } |
Można to wykonać w bardziej elegancki i poprawny sposób:
1 2 3 4 5 6 7 8 9 10 |
someSubscriptions : new Subscription(); ngOnInit() { this.someSubscriptions.add(...subscribe(...)); this.someSubscriptions.add(...subscribe(...)); } ngOnDestroy() { this.someSubscriptions.unsubscribe(); } |
Tworzymy nową instancję Subscription, a następnie do metody ADD, przekazujemy jako parametr nasze subscribes. Dzięki temu, możemy jednym unsubscribe(), odpiąć się od wszystkich subskrypcji, dodatkowo nie dostaniemy błędu, jeśli nie są zdefiniowane.
4. Barrels
Barrel to moduł, który reexportuje wybrane export’y innych modułów.
Często w modułach widzimy podobny kod:
1 2 3 4 |
import { UsersComponent } from '../users/users.component.ts'; import { UserDetailsComponent } from '../users/user-details.component.ts'; import { UserHeaderComponent } from '../users/user-header.component.ts'; import { UsersService } from '../users/users.service.ts'; |
Możemy zoptymalizować nasze importy, za pomocą stworzenia wspomnianego Barrel’a. Tworzymy plik o nazwie index.ts w tym samym katalogu gdzie znajdują się nasze komponenty lub foldery z komponentami (tutaj katalog users), a w nim umieszczamy następujący kod:
index.ts:
1 2 3 4 |
export * from './users.component'; export * from './user-details.component'; export * from './user-header.component'; export * from './users.service'; |
A następnie, możemy skonsolidować nasze importy do następującej formy:
1 2 3 4 5 6 |
import { UsersComponent, UserDetailsComponent, UserHeaderComponent, UsersService } from './users' |
5. Angular CLI i pliki spec.
Nie testujesz swojej aplikacji a denerwuje Cię automatyczne tworzenie plików .spec np. dla komponentów?
Wyłącz to w pliku w .angular-cli.json, w obiekcie „defaults”, ustawiając flagę spec na false:
1 2 3 4 5 6 7 8 9 10 11 |
"defaults": { "component": { "spec": false }, "directive": { "spec": false }, "service": { "spec": true } } |
Możesz również pozmieniać inne ustawienia, takie jak np. czy templatka ma być inline etc.
6. Plik tsconfig.json i optymalizacja importów
Często w aplikacji korzystamy np. z jednego serwisu lub jakiegoś pliku konfiguracyjnego na różnych poziomach katalogów. Prowadzi to do sytuacji, że nasz import wygląda następująco:
1 |
import { environment } from '../../../../environment'; |
Warto dodać takie katalogi / pliki jako paths w pliku tsconfig.json:
1 2 3 4 |
"baseUrl": "src", "paths": { "@env/*": ["environments/*"] } |
Należy również pamiętać, że ścieżki w paths są relatywne do baseUrl, czyli w powyższym przykładzie do katalogu src. Dzięki takiemu zabiegowi, możemy importować klasę environment w ten sposób:
1 |
import { environment } from '@env/environment'; |
7. Komponent jako atrybut
Spójrzmy na poniższy kod:
1 2 3 4 5 |
<table> <tr *ngFor="let row of rows"> .... content .... </tr> </table> |
Przeglądarka oczywiście wyrenderuje nam powyższe rzędy, żaden rocket science. Problem pojawia się, kiedy nasz rząd w tabeli wynosimy do zewnętrznego komponentu (my-tr-cmp):
1 2 3 |
<table> <my-tr-cmp *ngFor="let row of rows"></my-tr-cmp> </table> |
W tym momencie, nasza tabela się sypie na widoku, gdyż selektor „tr” jest opakowany w selektor komponentu, który zostaje zignorowany. Rozwiązaniem jest wykorzystanie komponentu jako atrybutu:
1 2 3 4 |
@Component({ selector: '[my-tr-cmp]', ... }) |
A następnie na widoku:
1 2 3 |
<table> <tr my-tr-cmp *ngFor="let row of rows"></tr> </table> |
Komponent może być również przekazany do widoku jako atrybut, w tym momencie omijamy opakowanie kodu w dodatkowy selektor komponentu i wszystko śmiga w naszej tabeli.
To na tyle, standardowo 7 tipów. Zapraszam również do odwiedzin poprzednich artykułów oraz zachęcam do lajkowania fanpage’a na FB, dzięki temu będziesz na bieżąco ze wszystkimi artykułami.
Nie działa mi „Plik tsconfig.json i optymalizacja importów” :/
hmm, „u mnie działa” 🙂 konsola rzuca jakieś logi podczas budowy projektu? lub być może edytujesz plik app.tsconfig.json?
lub może masz ten kod na githubie? w tym momencie ciężko mi pomóc nie widząc co wykonałeś
ad #5
w ng-cli 6
angular.json
„schematics”: {
„@schematics/angular:component”: {
„spec”: false
}
}
dzięki! tak jest, zaszły zmiany w nowszej wersji:)
Pingback: Angular Tips & Tricks cz. V - Angular.love