
<span awesomeTooltip="'Tooltip text'"> </span> <span [awesomeTooltip]="'Tooltip text'"> </span> 
<input type="text" name="fname" #inputTag> ViewChild decorator: class SomeComponent implements AfterViewInit { @ViewChild('inputTag') inputTag: ElementRef; ngAfterViewInit(){ const input$ = fromEvent(this.inputTag.nativeElement, 'keyUp') } ... } 
ViewChild returns undefined , look in the *ngIf template. <div *ngIf="someCondition"> <input type="text" name="fname" #inputTag> </div> ng-template above the problem element.ViewChild will be able to return a link to it in the ngAfterViewInit hook. <div [hidden]="!someCondition"> <input type="text" name="fname" #inputTag> </div> class SomeComponent { @ViewChild('inputTag') set inputTag(input: ElementRef|null) { if(!input) return; this.doSomething(input); } doSomething(input) { const input$ = keysfromEvent(input.nativeElement, 'keyup'); ... } } inputTag property, we create a stream from the data entered in the input field.ViewChild in Angular 8 can be static and dynamic.*ngFor . <div *ngFor="let item of itemsList; let i = index;" [customScroll] > <p *ngFor="let item of items" class="list-item">{{item}}</p> </div> scrollDirective.update to adjust the scrolling behavior taking into account the changes that occurred in the list.ngOnChanges hook: class SomeComponent implements OnChanges { @Input() itemsList = []; @ViewChild(CustomScrollDirective) scroll: CustomScrollDirective; ngOnChanges(changes) { if (changes.itemsList) { this.scroll.update(); } } ... } *ngFor terminates?*ngFor ( #listItems ) is #listItems . <div [customScroll]> <p *ngFor="let item of items" #listItems>{{item}}</p> </div> ViewChildren decorator. It returns an entity of type QueryList .QueryList class has a read-only changes property that QueryList events each time the list changes. class SomeComponent implements AfterViewInit { @Input() itemsList = []; @ViewChild(CustomScrollDirective) scroll: CustomScrollDirective; @ViewChildren('listItems') listItems: QueryList<any>; private sub: Subscription; ngAfterViewInit() { this.sub = this.listItems.changes.subscribe(() => this.scroll.update()) } ... } // app-routing.module.ts const routes: Routes = [ {path: '', redirectTo: '/home', pathMatch: 'full'}, {path: 'home', component: HomeComponent}, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], // #1 exports: [RouterModule] }) export class AppRoutingModule { } //app.module.ts @NgModule({ ... bootstrap: [AppComponent] // #2 }) export class AppModule { } // app.component.html <router-outlet></router-outlet> // #3 // app.component.ts export class AppComponent implements OnInit { title = 'QueryTest'; constructor(private route: ActivatedRoute) { } ngOnInit() { this.route.queryParams .subscribe(params => { console.log('saveToken', params); // #4 }); } } #x . Consider them:RouterModule there. The routes are configured so that if the route is not provided in the URL, we redirect the user to the /home page.AppComponent .AppComponent uses <router-outlet> to output the corresponding route components.queryParams for the route from the URL https://localhost:4400/home?accessToken=someTokenSequence queryParams will look like this: {accessToken: 'someTokenSequence'} 
queryParams object is queryParams twice. The first object is empty, it is issued during the initialization process of the Angular router. Only after that we get an object containing the request parameters (in our case, {accessToken: 'someTokenSequence'} ).
ActivatedRoute.queryParams . As usual - consider a step by step solution to the problem.paramsInUrl$ , will output data if the queryParams value queryParams not empty: export class AppComponent implements OnInit { constructor(private route: ActivatedRoute, private locationService: Location) { } ngOnInit() { // // const paramsInUrl$ = this.route.queryParams.pipe( filter(params => Object.keys(params).length > 0) ); ... } } noParamsInUrl$ , will output an empty value only if no request parameters were found in the URL: export class AppComponent implements OnInit { title = 'QueryTest'; constructor(private route: ActivatedRoute, private locationService: Location) { } ngOnInit() { ... // , , URL // const noParamsInUrl$ = this.route.queryParams.pipe( filter(() => !this.locationService.path().includes('?')), map(() => ({})) ); ... } } export class AppComponent implements OnInit { title = 'QueryTest'; constructor(private route: ActivatedRoute, private locationService: Location) { } ngOnInit() { // // const paramsInUrl$ = this.route.queryParams.pipe( filter(params => Object.keys(params).length > 0) ); // , , URL // const noParamsInUrl$ = this.route.queryParams.pipe( filter(() => !this.locationService.path().includes('?')), map(() => ({})) ); const params$ = merge(paramsInUrl$, noParamsInUrl$); params$.subscribe(params => { console.log('saveToken', params); }); } } param$ object param$ value only once - regardless of whether there is anything in the queryParams (an object with query parameters is issued) or not (an empty object is issued). // home.component.html <div class="wrapper" (mousemove)="mouseCoordinates = {x: $event.x, y: $event.y}"> <div *ngFor="let item of items"> <span>{{formatItem(item)}}</span> </div> </div> {{mouseCoordinates | json}} // home.component.ts export class HomeComponent { items = [1, 2, 3, 4, 5, 6]; mouseCoordinates = {}; formatItem(item) { // const t = Array.apply(null, Array(5)).map(() => 1); console.log('formatItem'); return item + '%'; } } formatItem method.
formatItem function). As a result, if some heavy calculations are performed in the template functions, this will put a load on the processor and affect how users will perceive the corresponding page.formatItem in advance and display the ready data on the page. // home.component.html <div class="wrapper" (mousemove)="mouseCoordinates = {x: $event.x, y: $event.y}"> <div *ngFor="let item of displayedItems"> <span>{{item}}</span> </div> </div> {{mouseCoordinates | json}} // home.component.ts @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.sass'] }) export class HomeComponent implements OnInit { items = [1, 2, 3, 4, 5, 6]; displayedItems = []; mouseCoordinates = {}; ngOnInit() { this.displayedItems = this.items.map((item) => this.formatItem(item)); } formatItem(item) { console.log('formatItem'); const t = Array.apply(null, Array(5)).map(() => 1); return item + '%'; } } 
mousemove event still leads to the launch of a change check. But, since we need the coordinates of the mouse, we cannot get rid of it.mousemove event handler only needs to perform some calculations (which do not affect what is displayed on the page), then to speed up the application, you can do the following:NgZone.runOutsideOfAngular inside the event handler function. This prevents the launch of a change check when a mousemove event mousemove (this will affect this handler exclusively). * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // 
Source: https://habr.com/ru/post/459304/
All Articles