Skip to content

Commit f15f411

Browse files
sheikalthafthePunderWoman
authored andcommitted
refactor(docs-infra): migrate adev to signal-based queries (#58646)
Used migration schametic to migrate to signal based queries and little manual migration where setter is used PR Close #58646
1 parent b972249 commit f15f411

File tree

10 files changed

+77
-80
lines changed

10 files changed

+77
-80
lines changed

adev/shared-docs/components/viewers/example-viewer/example-viewer.component.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
Input,
2222
signal,
2323
Type,
24-
ViewChild,
24+
viewChild,
2525
} from '@angular/core';
2626
import {CommonModule, DOCUMENT} from '@angular/common';
2727
import {MatTabGroup, MatTabsModule} from '@angular/material/tabs';
@@ -54,7 +54,7 @@ export class ExampleViewer {
5454

5555
@Input() githubUrl: string | null = null;
5656
@Input() stackblitzUrl: string | null = null;
57-
@ViewChild('codeTabs') matTabGroup?: MatTabGroup;
57+
readonly matTabGroup = viewChild<MatTabGroup>('codeTabs');
5858

5959
private readonly changeDetector = inject(ChangeDetectorRef);
6060
private readonly clipboard = inject(Clipboard);
@@ -111,7 +111,7 @@ export class ExampleViewer {
111111
`example-${this.exampleMetadata()?.id.toString()!}`,
112112
);
113113

114-
this.matTabGroup?.realignInkBar();
114+
this.matTabGroup()?.realignInkBar();
115115

116116
this.listenToMatTabIndexChange();
117117

@@ -142,8 +142,9 @@ export class ExampleViewer {
142142
}
143143

144144
private listenToMatTabIndexChange(): void {
145-
this.matTabGroup?.realignInkBar();
146-
this.matTabGroup?.selectedIndexChange
145+
const matTabGroup = this.matTabGroup();
146+
matTabGroup?.realignInkBar();
147+
matTabGroup?.selectedIndexChange
147148
.pipe(takeUntilDestroyed(this.destroyRef))
148149
.subscribe((index) => {
149150
this.snippetCode.set(this.exampleMetadata()?.files[index]);

adev/src/app/core/layout/progress-bar/progress-bar.component.spec.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ describe('ProgressBarComponent', () => {
2929
// We suspect a racing condition inside the RouterTestingHarness.
3030
// Until this has been investigated, we will skip this test.
3131
xit('should call progressBar.complete() on route change', async () => {
32-
const progressBar = component.progressBar();
33-
const progressBarCompleteSpy = spyOn(progressBar, 'complete');
32+
const progressBarCompleteSpy = spyOn(component.progressBar(), 'complete');
3433

3534
const harness = await RouterTestingHarness.create();
3635
await harness.navigateByUrl('/');

adev/src/app/core/layout/progress-bar/progress-bar.component.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
inject,
1313
OnInit,
1414
PLATFORM_ID,
15-
Signal,
1615
viewChild,
1716
} from '@angular/core';
1817
import {isPlatformBrowser} from '@angular/common';
@@ -41,7 +40,7 @@ export const PROGRESS_BAR_DELAY = 30;
4140
export class ProgressBarComponent implements OnInit {
4241
private readonly router = inject(Router);
4342

44-
progressBar = viewChild.required(NgProgressRef);
43+
readonly progressBar = viewChild.required(NgProgressRef);
4544

4645
isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
4746

adev/src/app/editor/code-editor/code-editor.component.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ describe('CodeEditor', () => {
9797
component.ngAfterViewInit();
9898

9999
expect(codeMirrorEditorInitSpy).toHaveBeenCalledWith(
100-
component['codeEditorWrapperRef'].nativeElement,
100+
component.codeEditorWrapperRef().nativeElement,
101101
);
102102
});
103103

adev/src/app/editor/code-editor/code-editor.component.ts

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ import {
1515
ElementRef,
1616
EnvironmentInjector,
1717
OnDestroy,
18-
ViewChild,
18+
afterRenderEffect,
1919
inject,
2020
signal,
21+
viewChild,
2122
} from '@angular/core';
2223
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
2324
import {MatTabGroup, MatTabsModule} from '@angular/material/tabs';
@@ -60,28 +61,13 @@ const ANGULAR_DEV = 'https://angular.dev';
6061
],
6162
})
6263
export class CodeEditor implements AfterViewInit, OnDestroy {
63-
@ViewChild('codeEditorWrapper') private codeEditorWrapperRef!: ElementRef<HTMLDivElement>;
64-
@ViewChild(MatTabGroup) private matTabGroup!: MatTabGroup;
65-
66-
private createFileInputRef?: ElementRef<HTMLInputElement>;
67-
@ViewChild('createFileInput') protected set setFileInputRef(
68-
element: ElementRef<HTMLInputElement>,
69-
) {
70-
if (element) {
71-
element.nativeElement.focus();
72-
this.createFileInputRef = element;
73-
}
74-
}
64+
readonly codeEditorWrapperRef =
65+
viewChild.required<ElementRef<HTMLDivElement>>('codeEditorWrapper');
66+
readonly matTabGroup = viewChild.required(MatTabGroup);
7567

76-
private renameFileInputRef?: ElementRef<HTMLInputElement>;
77-
@ViewChild('renameFileInput') protected set setRenameFileInputRef(
78-
element: ElementRef<HTMLInputElement>,
79-
) {
80-
if (element) {
81-
element.nativeElement.focus();
82-
this.renameFileInputRef = element;
83-
}
84-
}
68+
readonly createFileInputRef = viewChild<ElementRef<HTMLInputElement>>('createFileInput');
69+
70+
readonly renameFileInputRef = viewChild<ElementRef<HTMLInputElement>>('renameFileInput');
8571

8672
private readonly destroyRef = inject(DestroyRef);
8773

@@ -117,8 +103,20 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
117103
readonly isCreatingFile = signal<boolean>(false);
118104
readonly isRenamingFile = signal<boolean>(false);
119105

106+
constructor() {
107+
afterRenderEffect(() => {
108+
const createFileInput = this.createFileInputRef();
109+
createFileInput?.nativeElement.focus();
110+
});
111+
112+
afterRenderEffect(() => {
113+
const renameFileInput = this.renameFileInputRef();
114+
renameFileInput?.nativeElement.focus();
115+
});
116+
}
117+
120118
ngAfterViewInit() {
121-
this.codeMirrorEditor.init(this.codeEditorWrapperRef.nativeElement);
119+
this.codeMirrorEditor.init(this.codeEditorWrapperRef().nativeElement);
122120
this.listenToDiagnosticsChange();
123121

124122
this.listenToTabChange();
@@ -164,24 +162,25 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
164162

165163
async deleteFile(filename: string) {
166164
await this.codeMirrorEditor.deleteFile(filename);
167-
this.matTabGroup.selectedIndex = 0;
165+
this.matTabGroup().selectedIndex = 0;
168166
}
169167

170168
onAddButtonClick() {
171169
this.isCreatingFile.set(true);
172-
this.matTabGroup.selectedIndex = this.files().length;
170+
this.matTabGroup().selectedIndex = this.files().length;
173171
}
174172

175173
onRenameButtonClick() {
176174
this.isRenamingFile.set(true);
177175
}
178176

179177
async renameFile(event: SubmitEvent, oldPath: string) {
180-
if (!this.renameFileInputRef) return;
178+
const renameFileInput = this.renameFileInputRef();
179+
if (!renameFileInput) return;
181180

182181
event.preventDefault();
183182

184-
const renameFileInputValue = this.renameFileInputRef.nativeElement.value;
183+
const renameFileInputValue = renameFileInput.nativeElement.value;
185184

186185
if (renameFileInputValue) {
187186
if (renameFileInputValue.includes('..')) {
@@ -204,11 +203,12 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
204203
}
205204

206205
async createFile(event: SubmitEvent) {
207-
if (!this.createFileInputRef) return;
206+
const fileInput = this.createFileInputRef();
207+
if (!fileInput) return;
208208

209209
event.preventDefault();
210210

211-
const newFileInputValue = this.createFileInputRef.nativeElement.value;
211+
const newFileInputValue = fileInput.nativeElement.value;
212212

213213
if (newFileInputValue) {
214214
if (newFileInputValue.includes('..')) {
@@ -248,13 +248,13 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
248248
)
249249
.subscribe(() => {
250250
// selected file on project change is always the first
251-
this.matTabGroup.selectedIndex = 0;
251+
this.matTabGroup().selectedIndex = 0;
252252
});
253253
}
254254

255255
private listenToTabChange() {
256-
this.matTabGroup.selectedIndexChange
257-
.pipe(takeUntilDestroyed(this.destroyRef))
256+
this.matTabGroup()
257+
.selectedIndexChange.pipe(takeUntilDestroyed(this.destroyRef))
258258
.subscribe((index) => {
259259
const selectedFile = this.files()[index];
260260

adev/src/app/editor/embedded-editor.component.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ import {
1717
OnDestroy,
1818
OnInit,
1919
PLATFORM_ID,
20-
ViewChild,
2120
computed,
2221
inject,
2322
signal,
23+
viewChild,
2424
} from '@angular/core';
2525
import {takeUntilDestroyed, toObservable} from '@angular/core/rxjs-interop';
2626
import {IconComponent} from '@angular/docs';
@@ -53,8 +53,8 @@ export const LARGE_EDITOR_HEIGHT_BREAKPOINT = 550;
5353
providers: [EditorUiState],
5454
})
5555
export class EmbeddedEditor implements OnInit, AfterViewInit, OnDestroy {
56-
@ViewChild('editorContainer') editorContainer!: ElementRef<HTMLDivElement>;
57-
@ViewChild(MatTabGroup) matTabGroup!: MatTabGroup;
56+
readonly editorContainer = viewChild.required<ElementRef<HTMLDivElement>>('editorContainer');
57+
readonly matTabGroup = viewChild(MatTabGroup);
5858

5959
private readonly platformId = inject(PLATFORM_ID);
6060
private readonly changeDetector = inject(ChangeDetectorRef);
@@ -120,7 +120,10 @@ export class EmbeddedEditor implements OnInit, AfterViewInit, OnDestroy {
120120
private setFirstTabAsActiveAfterResize(): void {
121121
this.displayPreviewInMatTabGroup$.subscribe(() => {
122122
this.changeDetector.detectChanges();
123-
this.matTabGroup.selectedIndex = 0;
123+
const matTabGroup = this.matTabGroup();
124+
if (matTabGroup) {
125+
matTabGroup.selectedIndex = 0;
126+
}
124127
});
125128
}
126129

@@ -138,11 +141,11 @@ export class EmbeddedEditor implements OnInit, AfterViewInit, OnDestroy {
138141
this.splitDirection = this.isLargeEmbeddedEditor() ? 'horizontal' : 'vertical';
139142
});
140143

141-
this.resizeObserver.observe(this.editorContainer.nativeElement);
144+
this.resizeObserver.observe(this.editorContainer().nativeElement);
142145
}
143146

144147
private isLargeEmbeddedEditor(): boolean {
145-
const editorContainer = this.editorContainer.nativeElement;
148+
const editorContainer = this.editorContainer().nativeElement;
146149
const width = editorContainer.offsetWidth;
147150
const height = editorContainer.offsetHeight;
148151

adev/src/app/editor/terminal/terminal.component.spec.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,4 @@ describe('Terminal', () => {
4747
it('should create', () => {
4848
expect(component).toBeTruthy();
4949
});
50-
51-
it('should register the terminal element on afterViewInit', () => {
52-
const terminalDebugElement = fixture.debugElement.query(By.css('.adev-terminal-output'));
53-
54-
component['terminalElementRef'] = terminalDebugElement;
55-
component.ngAfterViewInit();
56-
57-
expect(terminalHandlerSpy.registerTerminal).toHaveBeenCalledWith(
58-
TerminalType.READONLY,
59-
terminalDebugElement.nativeElement,
60-
);
61-
});
6250
});

adev/src/app/editor/terminal/terminal.component.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ import {
1313
DestroyRef,
1414
ElementRef,
1515
Input,
16-
ViewChild,
1716
ViewEncapsulation,
1817
inject,
18+
viewChild,
1919
} from '@angular/core';
2020

2121
import {debounceTime} from 'rxjs/operators';
@@ -35,15 +35,15 @@ import {Subject} from 'rxjs';
3535
})
3636
export class Terminal implements AfterViewInit {
3737
@Input({required: true}) type!: TerminalType;
38-
@ViewChild('terminalOutput') private terminalElementRef!: ElementRef<HTMLElement>;
38+
readonly terminalElementRef = viewChild.required<ElementRef<HTMLElement>>('terminalOutput');
3939

4040
private readonly destroyRef = inject(DestroyRef);
4141
private readonly terminalHandler = inject(TerminalHandler);
4242

4343
private readonly resize$ = new Subject<void>();
4444

4545
ngAfterViewInit() {
46-
this.terminalHandler.registerTerminal(this.type, this.terminalElementRef.nativeElement);
46+
this.terminalHandler.registerTerminal(this.type, this.terminalElementRef().nativeElement);
4747

4848
this.setResizeObserver();
4949

@@ -57,7 +57,7 @@ export class Terminal implements AfterViewInit {
5757
this.resize$.next();
5858
});
5959

60-
resizeObserver.observe(this.terminalElementRef.nativeElement);
60+
resizeObserver.observe(this.terminalElementRef().nativeElement);
6161

6262
this.destroyRef.onDestroy(() => resizeObserver.disconnect());
6363
}

adev/src/app/features/tutorial/tutorial.component.spec.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,13 @@ describe('Tutorial', () => {
137137
setupResetRevealAnswerValues();
138138
fixture.detectChanges();
139139

140-
if (!component.revealAnswerButton) throw new Error('revealAnswerButton is undefined');
140+
const revealAnswerButton = component.revealAnswerButton();
141+
if (!revealAnswerButton) throw new Error('revealAnswerButton is undefined');
141142

142143
const revealAnswerSpy = spyOn(component['embeddedTutorialManager'], 'revealAnswer');
143144
const resetRevealAnswerSpy = spyOn(component['embeddedTutorialManager'], 'resetRevealAnswer');
144145

145-
component.revealAnswerButton.nativeElement.click();
146+
revealAnswerButton.nativeElement.click();
146147

147148
expect(revealAnswerSpy).not.toHaveBeenCalled();
148149
expect(resetRevealAnswerSpy).toHaveBeenCalled();
@@ -152,42 +153,44 @@ describe('Tutorial', () => {
152153
setupRevealAnswerValues();
153154
fixture.detectChanges();
154155

155-
if (!component.revealAnswerButton) throw new Error('revealAnswerButton is undefined');
156+
const revealAnswerButton = component.revealAnswerButton();
157+
if (!revealAnswerButton) throw new Error('revealAnswerButton is undefined');
156158

157159
const embeddedTutorialManagerRevealAnswerSpy = spyOn(
158160
component['embeddedTutorialManager'],
159161
'revealAnswer',
160162
);
161-
component.revealAnswerButton.nativeElement.click();
163+
revealAnswerButton.nativeElement.click();
162164

163165
expect(embeddedTutorialManagerRevealAnswerSpy).toHaveBeenCalled();
164166

165167
await fixture.whenStable();
166168
fixture.detectChanges();
167169

168-
expect(component.revealAnswerButton.nativeElement.textContent?.trim()).toBe('Reset');
170+
expect(revealAnswerButton.nativeElement.textContent?.trim()).toBe('Reset');
169171
});
170172

171173
it('should not reveal the answer when button is disabled', async () => {
172174
setupDisabledRevealAnswerValues();
173175
fixture.detectChanges();
174176

175-
if (!component.revealAnswerButton) throw new Error('revealAnswerButton is undefined');
177+
const revealAnswerButton = component.revealAnswerButton();
178+
if (!revealAnswerButton) throw new Error('revealAnswerButton is undefined');
176179

177180
spyOn(component, 'canRevealAnswer').and.returnValue(false);
178181

179182
const handleRevealAnswerSpy = spyOn(component, 'handleRevealAnswer');
180183

181-
component.revealAnswerButton.nativeElement.click();
184+
revealAnswerButton.nativeElement.click();
182185

183-
expect(component.revealAnswerButton.nativeElement.getAttribute('disabled')).toBeDefined();
186+
expect(revealAnswerButton.nativeElement.getAttribute('disabled')).toBeDefined();
184187
expect(handleRevealAnswerSpy).not.toHaveBeenCalled();
185188
});
186189

187190
it('should not render the reveal answer button when there are no answers', () => {
188191
setupNoRevealAnswerValues();
189192
fixture.detectChanges();
190193

191-
expect(component.revealAnswerButton).toBe(undefined);
194+
expect(component.revealAnswerButton()).toBe(undefined);
192195
});
193196
});

0 commit comments

Comments
 (0)