Skip to content
This repository was archived by the owner on Dec 18, 2024. It is now read-only.

Commit bbdd1e1

Browse files
committed
build: enable strictPropertyInitialization
- fix related build errors - complete `this._destroyed` in `ngOnDestroy()` - replace use of deprecated `DomPortalHost` with `DomPortalOutlet`
1 parent 146b095 commit bbdd1e1

File tree

20 files changed

+192
-147
lines changed

20 files changed

+192
-147
lines changed

src/app/pages/component-category-list/component-category-list.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
1+
import {CommonModule} from '@angular/common';
12
import {Component, NgModule, OnDestroy, OnInit} from '@angular/core';
23
import {MatCardModule} from '@angular/material/card';
3-
import {CommonModule} from '@angular/common';
44
import {ActivatedRoute, Params, RouterModule} from '@angular/router';
5-
import {DocumentationItems, SECTIONS} from '../../shared/documentation-items/documentation-items';
6-
import {ComponentPageTitle} from '../page-title/page-title';
7-
import {SvgViewerModule} from '../../shared/svg-viewer/svg-viewer';
8-
import {Observable, combineLatest, Subscription} from 'rxjs';
9-
import {NavigationFocusModule} from '../../shared/navigation-focus/navigation-focus';
5+
import {combineLatest, Observable, Subscription} from 'rxjs';
106

7+
import {
8+
DocumentationItems,
9+
SECTIONS
10+
} from '../../shared/documentation-items/documentation-items';
11+
import {
12+
NavigationFocusModule
13+
} from '../../shared/navigation-focus/navigation-focus';
14+
import {SvgViewerModule} from '../../shared/svg-viewer/svg-viewer';
15+
import {ComponentPageTitle} from '../page-title/page-title';
1116

1217
@Component({
1318
selector: 'app-component-category-list',
1419
templateUrl: './component-category-list.html',
1520
styleUrls: ['./component-category-list.scss']
1621
})
1722
export class ComponentCategoryList implements OnInit, OnDestroy {
18-
params: Observable<Params>;
19-
routeParamSubscription: Subscription;
20-
_categoryListSummary: string;
23+
params: Observable<Params> | undefined;
24+
routeParamSubscription: Subscription = new Subscription();
25+
_categoryListSummary: string | undefined;
2126

2227
constructor(public docItems: DocumentationItems,
2328
public _componentPageTitle: ComponentPageTitle,

src/app/pages/component-list/component-list.ts

Whitespace-only changes.

src/app/pages/component-sidenav/component-sidenav.ts

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import {animate, state, style, transition, trigger} from '@angular/animations';
2+
import {CdkAccordionModule} from '@angular/cdk/accordion';
3+
import {BreakpointObserver} from '@angular/cdk/layout';
4+
import {CommonModule} from '@angular/common';
5+
import {HttpClientModule} from '@angular/common/http';
16
import {
27
Component,
38
Input,
@@ -8,38 +13,42 @@ import {
813
ViewChild,
914
ViewEncapsulation
1015
} from '@angular/core';
11-
import {DocumentationItems} from '../../shared/documentation-items/documentation-items';
16+
import {FormsModule} from '@angular/forms';
1217
import {MatIconModule} from '@angular/material/icon';
18+
import {MatListModule} from '@angular/material/list';
1319
import {MatSidenav, MatSidenavModule} from '@angular/material/sidenav';
20+
import {MatDrawerToggleResult} from '@angular/material/sidenav/drawer';
1421
import {ActivatedRoute, Params, RouterModule, Routes} from '@angular/router';
15-
import {CommonModule} from '@angular/common';
16-
import {ComponentHeaderModule} from '../component-page-header/component-page-header';
17-
import {FooterModule} from '../../shared/footer/footer';
1822
import {combineLatest, Observable, Subscription} from 'rxjs';
1923
import {map} from 'rxjs/operators';
20-
import {animate, state, style, transition, trigger} from '@angular/animations';
21-
import {CdkAccordionModule} from '@angular/cdk/accordion';
22-
import {BreakpointObserver} from '@angular/cdk/layout';
24+
25+
import {DocViewerModule} from '../../shared/doc-viewer/doc-viewer-module';
26+
import {
27+
DocumentationItems
28+
} from '../../shared/documentation-items/documentation-items';
29+
import {FooterModule} from '../../shared/footer/footer';
30+
import {
31+
NavigationFocusModule
32+
} from '../../shared/navigation-focus/navigation-focus';
33+
import {
34+
NavigationFocusService
35+
} from '../../shared/navigation-focus/navigation-focus.service';
36+
import {StackBlitzButtonModule} from '../../shared/stack-blitz';
37+
import {SvgViewerModule} from '../../shared/svg-viewer/svg-viewer';
2338
import {
2439
ComponentCategoryList,
2540
ComponentCategoryListModule
2641
} from '../component-category-list/component-category-list';
42+
import {
43+
ComponentHeaderModule
44+
} from '../component-page-header/component-page-header';
2745
import {
2846
ComponentApi,
2947
ComponentExamples,
3048
ComponentOverview,
3149
ComponentViewer,
3250
ComponentViewerModule
3351
} from '../component-viewer/component-viewer';
34-
import {DocViewerModule} from '../../shared/doc-viewer/doc-viewer-module';
35-
import {FormsModule} from '@angular/forms';
36-
import {HttpClientModule} from '@angular/common/http';
37-
import {StackBlitzButtonModule} from '../../shared/stack-blitz';
38-
import {SvgViewerModule} from '../../shared/svg-viewer/svg-viewer';
39-
import {MatDrawerToggleResult} from '@angular/material/sidenav/drawer';
40-
import {MatListModule} from '@angular/material/list';
41-
import {NavigationFocusModule} from '../../shared/navigation-focus/navigation-focus';
42-
import {NavigationFocusService} from '../../shared/navigation-focus/navigation-focus.service';
4352

4453
// These constants are used by the ComponentSidenav for orchestrating the MatSidenav in a responsive
4554
// way. This includes hiding the sidenav, defaulting it to open, changing the mode from over to
@@ -58,8 +67,8 @@ const SMALL_WIDTH_BREAKPOINT = 959;
5867
encapsulation: ViewEncapsulation.None,
5968
})
6069
export class ComponentSidenav implements OnInit, OnDestroy {
61-
@ViewChild(MatSidenav) sidenav: MatSidenav;
62-
params: Observable<Params>;
70+
@ViewChild(MatSidenav) sidenav!: MatSidenav;
71+
params: Observable<Params> | undefined;
6372
isExtraScreenSmall: Observable<boolean>;
6473
isScreenSmall: Observable<boolean>;
6574
private subscriptions = new Subscription();
@@ -112,8 +121,8 @@ export class ComponentSidenav implements OnInit, OnDestroy {
112121
],
113122
})
114123
export class ComponentNav {
115-
@Input() params: Observable<Params>;
116-
currentItemId: string;
124+
@Input() params: Observable<Params> | undefined;
125+
currentItemId: string | undefined;
117126

118127
constructor(public docItems: DocumentationItems) {}
119128
}

src/app/pages/component-viewer/component-viewer.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,9 @@ export class ComponentViewer implements OnDestroy {
3636
sections: Set<string> = new Set(['overview', 'api']);
3737
private _destroyed = new Subject();
3838

39-
constructor(_route: ActivatedRoute,
40-
private router: Router,
39+
constructor(_route: ActivatedRoute, private router: Router,
4140
public _componentPageTitle: ComponentPageTitle,
42-
public docItems: DocumentationItems,
43-
) {
41+
public docItems: DocumentationItems) {
4442
const routeAndParentParams = [_route.params];
4543
if (_route.parent) {
4644
routeAndParentParams.push(_route.parent.params);
@@ -78,12 +76,11 @@ export class ComponentViewer implements OnDestroy {
7876
*/
7977
@Directive()
8078
export class ComponentBaseView implements OnInit, OnDestroy {
81-
@ViewChild('toc') tableOfContents: TableOfContents;
82-
@ViewChildren(DocViewer) viewers: QueryList<DocViewer>;
79+
@ViewChild('toc') tableOfContents!: TableOfContents;
80+
@ViewChildren(DocViewer) viewers!: QueryList<DocViewer>;
8381

8482
showToc: Observable<boolean>;
85-
86-
destroyed = new Subject<void>();
83+
private _destroyed = new Subject();
8784

8885
constructor(
8986
public componentViewer: ComponentViewer,
@@ -99,15 +96,15 @@ export class ComponentBaseView implements OnInit, OnDestroy {
9996
}
10097

10198
ngOnInit() {
102-
this.componentViewer.componentDocItem.pipe(takeUntil(this.destroyed)).subscribe(() => {
99+
this.componentViewer.componentDocItem.pipe(takeUntil(this._destroyed)).subscribe(() => {
103100
if (this.tableOfContents) {
104101
this.tableOfContents.resetHeaders();
105102
}
106103
});
107104

108105
this.showToc.pipe(
109106
skip(1),
110-
takeUntil(this.destroyed)
107+
takeUntil(this._destroyed)
111108
).subscribe(() => {
112109
if (this.tableOfContents) {
113110
this.viewers.forEach(viewer => {
@@ -118,7 +115,8 @@ export class ComponentBaseView implements OnInit, OnDestroy {
118115
}
119116

120117
ngOnDestroy() {
121-
this.destroyed.next();
118+
this._destroyed.next();
119+
this._destroyed.complete();
122120
}
123121

124122
updateTableOfContents(sectionName: string, docViewerContent: HTMLElement, sectionIndex = 0) {

src/app/shared/carousel/carousel.spec.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,5 @@ describe('HorizontalCarousel', () => {
9999
})
100100
class CarouselTestComponent {
101101
numberOfItems = 6;
102-
@ViewChild(Carousel) carousel: Carousel;
102+
@ViewChild(Carousel) carousel!: Carousel;
103103
}
104-

src/app/shared/carousel/carousel.ts

Lines changed: 66 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,19 @@ export class CarouselItem implements FocusableOption {
3636
encapsulation: ViewEncapsulation.None
3737
})
3838
export class Carousel implements AfterContentInit {
39-
@Input('aria-label') ariaLabel: string;
40-
@Input() itemWidth: number;
41-
@ContentChildren(CarouselItem) items: QueryList<CarouselItem>;
42-
@ViewChild('contentWrapper') wrapper: ElementRef;
39+
@Input('aria-label') ariaLabel: string | undefined;
40+
@Input() itemWidth: number | undefined;
41+
@ContentChildren(CarouselItem) items!: QueryList<CarouselItem>;
42+
@ViewChild('contentWrapper') wrapper!: ElementRef;
4343
position = 0;
4444
showPrevArrow = false;
4545
showNextArrow = true;
46-
visibleItems: number;
47-
shiftWidth: number;
48-
itemsArray: CarouselItem[];
49-
private focusKeyManager: FocusKeyManager<CarouselItem>;
46+
visibleItems: number | undefined;
47+
shiftWidth: number | undefined;
48+
itemsArray: CarouselItem[] | undefined;
49+
private focusKeyManager: FocusKeyManager<CarouselItem> | undefined;
5050

51-
constructor(private readonly element: ElementRef) {
52-
}
51+
constructor(private readonly element: ElementRef) {}
5352

5453
private _index = 0;
5554

@@ -59,37 +58,44 @@ export class Carousel implements AfterContentInit {
5958

6059
set index(i: number) {
6160
this._index = i;
61+
let lastVisibleIndex = this.items.length;
62+
if (this.visibleItems) {
63+
lastVisibleIndex -= this.visibleItems;
64+
}
65+
6266
this.showPrevArrow = i > 0;
63-
this.showNextArrow = i < (this.items.length - this.visibleItems);
67+
this.showNextArrow = i < lastVisibleIndex;
6468
}
6569

6670
onKeydown(event: KeyboardEvent) {
67-
switch (event.key) {
68-
case 'Tab':
69-
if (!this.focusKeyManager.activeItem) {
70-
this.focusKeyManager.setFirstItemActive();
71+
if (this.focusKeyManager != null) {
72+
switch (event.key) {
73+
case 'Tab':
74+
if (!this.focusKeyManager.activeItem) {
75+
this.focusKeyManager.setFirstItemActive();
76+
this._updateItemTabIndices();
77+
}
78+
break;
79+
80+
case 'ArrowLeft':
81+
if (this.focusKeyManager.activeItemIndex === this.index) {
82+
this.previous();
83+
}
84+
this.focusKeyManager.setPreviousItemActive();
7185
this._updateItemTabIndices();
72-
}
73-
break;
86+
break;
7487

75-
case 'ArrowLeft':
76-
if (this.focusKeyManager.activeItemIndex === this.index) {
77-
this.previous();
78-
}
79-
this.focusKeyManager.setPreviousItemActive();
80-
this._updateItemTabIndices();
81-
break;
82-
83-
case 'ArrowRight':
84-
if (this.focusKeyManager.activeItemIndex === this.index + this.visibleItems - 1) {
85-
this.next();
86-
}
87-
this.focusKeyManager.setNextItemActive();
88-
this._updateItemTabIndices();
89-
break;
88+
case 'ArrowRight':
89+
if (this.focusKeyManager.activeItemIndex === this.index + (this.visibleItems || 0) - 1) {
90+
this.next();
91+
}
92+
this.focusKeyManager.setNextItemActive();
93+
this._updateItemTabIndices();
94+
break;
9095

91-
default:
92-
break;
96+
default:
97+
break;
98+
}
9399
}
94100
}
95101

@@ -103,7 +109,7 @@ export class Carousel implements AfterContentInit {
103109
// timeout to make sure clientWidth is defined
104110
setTimeout(() => {
105111
this.itemsArray = this.items.toArray();
106-
this.shiftWidth = this.items.first.element.nativeElement.clientWidth;
112+
this.shiftWidth = this.calculateShiftWidth(this.itemsArray);
107113
this._resizeCarousel();
108114
});
109115
}
@@ -122,35 +128,52 @@ export class Carousel implements AfterContentInit {
122128
}
123129
}
124130

131+
/**
132+
* @param items array of carousel items
133+
* @return width to shift the carousel
134+
*/
135+
calculateShiftWidth(items: CarouselItem[]): number {
136+
return items[0].element.nativeElement.clientWidth;
137+
}
138+
125139
private _updateItemTabIndices() {
126140
this.items.forEach((item: CarouselItem) => {
127-
item.tabindex = item === this.focusKeyManager.activeItem ? '0' : '-1';
141+
if (this.focusKeyManager != null) {
142+
item.tabindex = item === this.focusKeyManager.activeItem ? '0' : '-1';
143+
}
128144
});
129145
}
130146

131147
private _shiftItems(shiftIndex: number) {
132148
this.index += shiftIndex;
133-
this.position += shiftIndex * this.shiftWidth;
149+
this.position += shiftIndex *
150+
(this.shiftWidth || this.calculateShiftWidth(this.items.toArray()));
134151
this.items.forEach((item: CarouselItem) => {
135152
item.element.nativeElement.style.transform = `translateX(-${this.position}px)`;
136153
});
137154
}
138155

139156
private _resizeCarousel() {
157+
if (this.shiftWidth == null) {
158+
this.shiftWidth = this.calculateShiftWidth(this.items.toArray());
159+
}
140160
const newVisibleItems = Math.max(1, Math.min(
141161
Math.floor((this.element.nativeElement.offsetWidth) / this.shiftWidth),
142162
this.items.length));
143163
if (this.visibleItems !== newVisibleItems) {
144-
if (this.visibleItems < newVisibleItems) {
145-
const shiftIndex = this.index - (this.items.length - this.visibleItems) + 1;
164+
if ((this.visibleItems || 0) < newVisibleItems) {
165+
const lastVisibleIndex = this.items.length - (this.visibleItems || 0);
166+
const shiftIndex = this.index - (lastVisibleIndex) + 1;
146167
if (shiftIndex > 0) {
147168
this._shiftItems(-shiftIndex);
148169
}
149170
} else {
150-
if (this.focusKeyManager.activeItemIndex && this.focusKeyManager.activeItemIndex >
151-
this.index + newVisibleItems - 1) {
152-
this.focusKeyManager.setPreviousItemActive();
153-
this._updateItemTabIndices();
171+
if (this.focusKeyManager != null) {
172+
if (this.focusKeyManager.activeItemIndex && this.focusKeyManager.activeItemIndex >
173+
this.index + newVisibleItems - 1) {
174+
this.focusKeyManager.setPreviousItemActive();
175+
this._updateItemTabIndices();
176+
}
154177
}
155178
}
156179
this.visibleItems = newVisibleItems;
@@ -159,4 +182,3 @@ export class Carousel implements AfterContentInit {
159182
this.wrapper.nativeElement.style.width = `${this.visibleItems * this.shiftWidth}px`;
160183
}
161184
}
162-

src/app/shared/doc-viewer/doc-viewer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ import {HeaderLink} from './header-link';
2626
})
2727
export class DocViewer implements OnDestroy {
2828
private _portalHosts: DomPortalOutlet[] = [];
29-
private _documentFetchSubscription: Subscription;
29+
private _documentFetchSubscription: Subscription = new Subscription();
3030

31-
@Input() name: string;
31+
@Input() name: string | undefined;
3232

3333
/** The URL of the document to display. */
3434
@Input()

src/app/shared/doc-viewer/header-link.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class HeaderLink {
2929
* Id of the anchor element. Note that is uses "example" because we instantiate the
3030
* header link components through the ComponentPortal.
3131
*/
32-
@Input() example: string;
32+
@Input() example: string | undefined;
3333

3434
/** Base URL that is used to build an absolute fragment URL. */
3535
private _baseUrl: string;

src/app/shared/example-viewer/code-snippet.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ import {DocViewer} from '../doc-viewer/doc-viewer';
1313
changeDetection: ChangeDetectionStrategy.OnPush
1414
})
1515
export class CodeSnippet {
16-
@Input() source: string;
17-
@ViewChild('viewer') viewer: DocViewer;
16+
@Input() source: string | undefined;
17+
@ViewChild('viewer') viewer!: DocViewer;
1818
}

0 commit comments

Comments
 (0)