Skip to content

Instantly share code, notes, and snippets.

@yokoishioka
Last active July 28, 2020 15:48
Show Gist options
  • Save yokoishioka/6d4938dd3cfcae957e881b0a890ffa27 to your computer and use it in GitHub Desktop.
Save yokoishioka/6d4938dd3cfcae957e881b0a890ffa27 to your computer and use it in GitHub Desktop.
test angular lifecycles
.log {
.header {
display: flex;
justify-content: space-between;
}
.body {
position: absolute;
height: 50vh;
width: 100%;
overflow: auto;
}
p {
font-size: 0.8rem;
margin-bottom: 0.5em;
}
.info {
color: aquamarine;
}
}
import { Component, OnInit, Input } from '@angular/core';
import { TestLifecyclesService } from '../../test-lifecycles.service';
import { TestLifecyclesLog } from '../../tests';
import { Subscription } from 'rxjs';
@Component({
selector: 'ces-test-lifecycles-log',
templateUrl: './test-lifecycles-log.component.html',
styleUrls: ['./test-lifecycles-log.component.scss']
})
export class TestLifecyclesLogComponent implements OnInit {
@Input() logs: TestLifecyclesLog[] = [];
logs$: Subscription;
constructor(
private cycles: TestLifecyclesService
) { }
ngOnInit(): void {
this.logs$ = this.cycles.log$.pipe().subscribe(log => {
this.logs ? this.logs.push(log) : this.logs = [];
});
}
ngOnDestroy() {
if (this.logs$) {
this.logs$.unsubscribe;
}
}
resetLog() {
this.logs = undefined;
}
}
<aside class="log">
<div class="header">
<h2>Lifecycles Log</h2>
<ces-button padding="0.5rem" (click)="resetLog()">Reset log</ces-button>
</div>
<div #log class="body">
<ng-container *ngIf="logs">
<p *ngFor="let log of logs; let i = index;" [style]="{'color': log.styles}">{{ i }} : {{ log.source }} :
{{ log.message }}</p>
</ng-container>
</div>
</aside>
import { Directive, OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy, Input, ElementRef, HostListener, Renderer2 } from '@angular/core';
import { TestLifecyclesMap } from '../tests';
import { TestLifecyclesService } from '../test-lifecycles.service';
import { Subscription } from 'rxjs';
import { TestsService } from '../tests.service';
import { ActivatedRoute } from '@angular/router';
@Directive({
selector: '[cesTestLifecycles]'
})
export class TestLifecyclesDirective implements OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewChecked, AfterViewInit, AfterContentChecked, OnDestroy {
@Input() logClick: boolean = true;
@Input() logKeydown: boolean = true;
@Input() logChange: boolean = true;
@Input() logCycle: boolean = true;
@Input() source: string;
@Input() ignore: boolean = false;
cycle: string;
constructor(
private cycles: TestLifecyclesService,
private tests: TestsService,
private route: ActivatedRoute,
private el: ElementRef,
private renderer: Renderer2
) { }
@HostListener('click', [('$event')]) onClick(event) {
if (this.logClick) {
this.source = event.target.type;
this.cycles.setAction(event.type, this.source)
}
}
@HostListener('keydown', [('$event')]) onKeydown(event) {
if (this.logKeydown) {
this.source = event.target.type;
this.cycles.setAction(`${event.type} (${event.key})`, `${this.source}`)
}
}
@HostListener('change', [('$event')]) onChange(event) {
// console.log('change')
// console.log(event)
// console.log(event.path[0])
// console.log(event.target.type)
// console.log(this.el)
// console.log(this.el.nativeElement.parentElement)
if (this.logChange) {
this.source = event.target.type;
this.cycles.setAction(event.type, this.source)
}
}
ngOnChanges() {
this.cycle = TestLifecyclesMap.cycle.ngOnChanges;
this.setCycle(this.cycle);
}
ngOnInit(): void {
this.cycle = TestLifecyclesMap.cycle.ngOnInit;
this.setCycle(this.cycle);
}
ngDoCheck() {
this.cycle = TestLifecyclesMap.cycle.ngDoCheck;
this.setCycle(this.cycle);
}
ngAfterContentInit() {
this.cycle = TestLifecyclesMap.cycle.ngAfterContentInit;
this.setCycle(this.cycle);
}
ngAfterContentChecked() {
this.cycle = TestLifecyclesMap.cycle.ngAfterContentChecked;
this.setCycle(this.cycle);
}
ngAfterViewInit() {
this.cycle = TestLifecyclesMap.cycle.ngAfterViewInit;
this.setCycle(this.cycle);
}
ngAfterViewChecked() {
this.cycle = TestLifecyclesMap.cycle.ngAfterViewChecked;
this.setCycle(this.cycle);
}
ngOnDestroy() {
this.cycle = TestLifecyclesMap.cycle.ngOnDestroy;
this.setCycle(this.cycle);
}
setCycle(cycle: string) {
if (this.logClick || this.logChange || this.logKeydown) {
this.source = this.el.nativeElement.localName;
this.cycles.setCycle(cycle, this.source);
}
}
}
import { Injectable } from '@angular/core';
import { Subject, Observable, BehaviorSubject } from 'rxjs';
import { TestLifecyclesLog } from './tests';
@Injectable({
providedIn: 'root'
})
export class TestLifecyclesService {
cycle$: Subject<any> = new Subject();
action$: Subject<any> = new Subject();
log$: Subject<TestLifecyclesLog> = new Subject();
constructor() { }
setCycle(cycle: string, source: string): Observable<string> {
const log: TestLifecyclesLog = {
message: cycle,
source: source || 'cycle',
styles: 'aquamarine'
};
this.setLog(log);
this.cycle$.next(cycle);
return this.cycle$;
}
endCycle() {
this.cycle$.unsubscribe();
}
setAction(action: string, source: string): Observable<string> {
const log: TestLifecyclesLog = {
message: action,
source: source || 'action',
styles: 'tomato'
};
this.setLog(log);
this.action$.next(action);
return this.action$;
}
endAction() {
this.action$.unsubscribe();
}
setLog(log: TestLifecyclesLog): Observable<TestLifecyclesLog> {
this.log$.next(log);
return this.log$;
}
endLog() {
this.log$.unsubscribe();
}
}
export const TestLifecyclesMap = {
cycle: {
constructor: 'Constructor',
ngOnChanges: 'On Changes',
ngOnInit: 'On Init',
ngDoCheck: 'Do Check',
ngAfterContentInit: 'After Content Init',
ngAfterContentChecked: 'After Content Checked',
ngAfterViewInit: 'After View Init',
ngAfterViewChecked: 'After View Checked',
ngOnDestroy: 'On Destroy'
}
}
export interface TestLifecyclesLog {
message: string,
source?: string,
styles?: string
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment