Witam w kolejnym artykule z serii Angular Tips & Tricks! Wg statystyk Google Analitycs, cieszy się największą ilością wyświetleń, więc postaram się częściej dodawać arty z tej z serii. Zatem do meritum!:)
1. Wstrzymanie EventEmmitera
Zapewne jak wiesz, komponent dziecko może się komunikować z komponentem rodzicem poprzez dekorator @Output. Zdarzają się sytuacje, że chcemy wstrzymać możliwość wysyłania eventów. Jeden sposób, to odbiór parametru EventEmittera i dodanie odpowiedniego IFa, na który powiedzmy funkcja nasłuchiwująca ma się od razu zakończyć. Jednak w ten sposób nadal wysyłamy eventy wysyłane poprzez emit().
Aby faktycznie wstrzymać wysyłanie eventów, musimy skorzystać z metody .complete() z biblioteki RxJS.
1 2 3 |
@Output() sayHello = new EventEmitter<string>(); ... this.sayHello.complete(); |
Poniżej plunker z przykładem, musisz otworzyć konsolę aby zobaczyć efekt:
2. Event keyup
Angular udostępnia nam łatwe obsługiwanie eventów, np za pomocą metody (click). Bardzo możliwe, że korzystałeś już z (keyup), np. w formularzach:
1 |
<input (keyup)="doSomething()"></input> |
Często w aplikacjach jest tak, że np pole automatycznie zatwierdza się po kliknięciu guzika enter, lub kliknięcie strzałkę w górę, wraca do ostatnio wpisanego tekstu. Zamiast dopisywać swój własny kod, na obsługę np. entera, możemy skorzystać ze sprecyzowanej metody keyup w jednej z poniższych postaci:
1 2 3 4 5 |
<input (keyup.enter)="doSomething()"></input> <input (keyup.arrowUp)="doSomething()"></input> <input (keyup.arrowDown)="doSomething()"></input> <input (keyup.esc)="doSomething()"></input> <input (keyup.arrowDown)="doSomething()" (keyup.arrowUp)="doSomething2()"></input> |
Znaczenie enter / arrowUp / arrowDown / esc, zakładam, że jest jasne:-).
3. valueChanges w ReactiveForms i unscubscription
Używając ReactiveForms, możemy nasłuchiwać na zmianę wartości konkretnej kontrolki w formularzu w następujący sposób:
1 2 3 4 |
const ctrl = new FormControl('', Validators.required); ctrl.valueChanges.subscribe((value) => { console.log(value); }); |
Trzeba pamiętać, że w tym przypadku, Angular nie odepnie subskrypcji za nas np. w przypadku opuszczenia widoku (komponentu), tak jak to robi automatycznie w większości przypadków.
Poprawne rozwiązanie:
1 2 3 4 5 6 7 8 9 10 |
ctrlSubscription : Subscription; const ctrl = new FormControl('', Validators.required); this.ctrlSubsscription = ctrl.valueChanges.subscribe((value) => { console.log(value); }); ngOnDestroy() { this.ctrlSubscription.unsubscribe(); } |
Zatem przypisujemy valueChanges.subscribe do pola klasy, a następnie w hooku ngOnDestroy, odpinamy się od subskrypcji.
4. Zmiana tytułu za pomocą klasy Title
Standardowo aplikacje SPA, posiadają ten sam tytuł na każdym widoku. No ale być może chcemy z jakiegoś powodu poprawić SEO naszej aplikacji? Angular udostępnia nam serwis Title. Jeśli chcemy aby widok z danym komponentem miał swój tytuł (tytuł widzimy zawsze u góry, w karcie przeglądarki), możemy to zrobić w następujący sposób:
1. Importujemy klasę Title z platform-browser, następnie dodajemy ją do providers w app.module.ts:
1 2 3 4 5 6 7 8 9 |
import { BrowserModule, Title } from ‘@angular/platform-browser’; @NgModule({ ... providers: [Title], ... }) export class AppModule {} |
2 . Przechodzimy do komponentu, wstrzykujemy serwis Title:
1 |
public constructor(private title : Title ) {} |
3. Klasa Title ma dwie metody, getTitle() oraz setTitle(string). Wykorzystamy setTitle do ustawienia tytułu:
1 2 3 |
ngOnInit { this.title.setTitle('My new page title'); } |
W tym momencie, w karcie ustawi się nasz nowy tytuł, gdy odwiedzimy nasz konkretny komponent.
5. Then i Else
Chyba już wszyscy się dowiedzieli, że Angular4 udostępnia nam “else” w *ngIf. Ale być może nie wiesz, że możesz skorzystać z “then”:
1 2 3 |
<div *ngIf="myCondition; then thenBlock else elseBlock"></div> <ng-template #thenBlock>Jeśli myCondition === true, to wyświetl ten template</ng-template> <ng-template #elseBlock>Jeśli myCondition === false, to wyświetl ten template</ng-template> |
6. Pipes nie tylko na widoku
Angular udostępnia nam Pipes, które najczęściej odpowiednio formatują nam wartości na widoku, np:
1 |
{{ 12 | percentPipe }} |
Dobrze wiedzieć, że dany Pipe możemy wstrzyknąć jako serwis do klasy komponentu. Najpierw musimy go zarejestrować w providers w app.module.ts (i oczywiście zaimportować):
1 2 3 4 5 |
@NgModule({ ... providers: [PercentPipe] ... }); |
Następnie w komponencie wstrzykujemy wybrany Pipe:
1 2 3 4 5 |
constructor(private percentPipe : PercentPipe) { const num = 12; const percentNum = this.percentPipe.transform(num); console.log(percentNum); } |
Wystarczy wywołać metodę transform, vuala:-)
7. Nasłuchiwanie na window events
Obiekt window może nasłuchiwać na takie eventy jak scroll, lub np. resize. W jQuery bardzo wygodnie się to robi:
1 |
$(window).on('resize', handler); |
Co ciekawe, w Angularze możemy zrobić to jeszcze prościej. Wystarczy w templatce przypisać event np do diva:
1 |
<div (window:resize)="onResize($event)">Some content</div> |
1 |
<div (window:scroll)="onScroll($event)">Some content</div> |
I w komponencie nasze handlery:
1 2 3 |
onResize(event) { console.log(event.target.innerWidth); } |
1 2 3 |
onScroll(event) { console.log('Say Hello'); } |
Generalnie ciekawa sprawa:) To by było na tyle w tym odcinku!
Przy resize/scroll nie trzeba używać diva z templatki, można wykorzystać HostListener
@HostListener(‘window:resize’, [‘$event’])
onResize(event) {
console.log(event.target.innerWidth);
}
oczywiście można zrobić tak jak mówisz. Bardziej chodziło o trick, z (window:scroll). Ale to nadal nie jest najlepsze rozwiązanie. Powinno się skorzystać z EventManagera i zrobić globalny event, zamiast w konkretnym komponencie użyć HostLinstenera. Poświęcę temu osobny artykuł, być może kolejny.
Pingback: Angular Tips & Tricks cz.IV - Angular.love