Skip to content

Commit b9f1453

Browse files
feat: Add an example for ViewChild Read and Static attribute.
1 parent 03289b3 commit b9f1453

File tree

9 files changed

+238
-2
lines changed

9 files changed

+238
-2
lines changed
132 KB
Loading

src/app/example1/a-component.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,65 @@ import { OnInit, AfterViewInit, SimpleChanges, OnChanges, DoCheck, AfterContentI
33

44
// tslint:disable-next-line: no-conflicting-lifecycle
55
export abstract class AComponent implements OnChanges, OnInit, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy {
6+
protected printRef = [] as (() => any)[];
7+
68
constructor() { }
79

810
ngOnChanges(changes: SimpleChanges): void {
911
// Called before any other lifecycle hook. Use it to inject dependencies, but avoid any serious work here.
1012
// Add '${implements OnChanges}' to the class.
1113
console.log('ngOnChanges', changes);
14+
this.print();
1215
}
1316

1417
ngOnInit(): void {
1518
// Called after the constructor, initializing input properties, and the first call to ngOnChanges.
1619
// Add 'implements OnInit' to the class.
1720
console.log('ngOnInit');
21+
this.print();
1822
}
1923

2024
ngDoCheck(): void {
2125
// Called every time that the input properties of a component or a directive are checked.
2226
// Use it to extend change detection by performing a custom check.
2327
// Add 'implements DoCheck' to the class.
2428
console.log('ngDoCheck');
29+
this.print();
2530
}
2631

2732
ngAfterContentInit(): void {
2833
// Called after ngOnInit when the component's or directive's content has been initialized.
2934
// Add 'implements AfterContentInit' to the class.
3035
console.log('ngAfterContentInit');
36+
this.print();
3137
}
3238

3339
ngAfterContentChecked(): void {
3440
// Called after every check of the component's or directive's content.
3541
// Add 'implements AfterContentChecked' to the class.
3642
console.log('ngAfterContentChecked');
43+
this.print();
3744
}
3845

3946
ngAfterViewInit(): void {
4047
// Called after ngAfterContentInit when the component's view has been initialized. Applies to components only.
4148
// Add 'implements AfterViewInit' to the class.
4249
console.log('ngAfterViewInit');
50+
this.print();
4351
}
4452

4553
ngAfterViewChecked(): void {
4654
// Called after every check of the component's view. Applies to components only.
4755
// Add 'implements AfterViewChecked' to the class.
4856
console.log('ngAfterViewChecked');
57+
this.print();
4958
}
5059

5160
ngOnDestroy(): void {
5261
// Called once, before the instance is destroyed.
5362
// Add 'implements OnDestroy' to the class.
5463
console.log('ngOnDestroy');
64+
this.print();
5565
}
5666

5767
cache = {};
@@ -62,4 +72,10 @@ export abstract class AComponent implements OnChanges, OnInit, DoCheck, AfterCon
6272
this.cache[title] = true;
6373
}
6474
}
75+
76+
private print() {
77+
for (const ref of this.printRef) {
78+
console.log(' > ', ref());
79+
}
80+
}
6581
}

src/app/example4/README.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
## ViewChild Static attribute ([link](https://angular.io/api/core/ViewChild))
2+
3+
- If static is set to False, angular will use [ɵɵstaticViewQuery](https://github.com/angular/angular/blob/698b0288bee60b8c5926148b79b5b93f454098db/packages/core/src/render3/query.ts#L456) (Creates new QueryList for a static view query).
4+
5+
- If static is set to True, Angular will use [ɵɵviewQuery](https://github.com/angular/angular/blob/698b0288bee60b8c5926148b79b5b93f454098db/packages/core/src/render3/query.ts#L470) (Creates new QueryList, stores the reference in LView and returns QueryList).
6+
7+
When Angular will call [ɵɵqueryRefresh](https://github.com/angular/angular/blob/698b0288bee60b8c5926148b79b5b93f454098db/packages/core/src/render3/query.ts#L431) method (*Refreshes a query by combining matches from all active views and removing matches from deleted views*) and if the query is static, it will be never refreshed after the creation of the view (improve performance), but now if the query is not static it will be refreshed each time (performance impact).
8+
9+
## Output compiler example
10+
11+
![Angular viewChild static attribute compiler output](./../../../assets/viewChild_Static_True_vs_False.JPG)
12+
13+
14+
```javascript
15+
// Static is set to True
16+
const _c0 = ["uc1"];
17+
const _c1 = ["uc2"];
18+
function Example4Component_div_0_Template(rf, ctx) { if (rf & 1) {
19+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵelementStart"](0, "div", null, 1);
20+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵelementStart"](2, "p");
21+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵtext"](3, "My amazing content !");
22+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵelementEnd"]();
23+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵelementEnd"]();
24+
} }
25+
class Example4Component extends _app_example1_a_component__WEBPACK_IMPORTED_MODULE_1__["AComponent"] {
26+
constructor() {
27+
super();
28+
// this.printRef.push(() => this.uc1);
29+
this.printRef.push(() => this.uc2);
30+
}
31+
}
32+
Example4Component.ɵfac = function Example4Component_Factory(t) { return new (t || Example4Component)(); };
33+
Example4Component.ɵcmp = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineComponent"]({ type: Example4Component, selectors: [["app-example4"]], viewQuery: function Example4Component_Query(rf, ctx) { if (rf & 1) {
34+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵstaticViewQuery"](_c0, true);
35+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵstaticViewQuery"](_c1, true);
36+
} if (rf & 2) {
37+
var _t;
38+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵloadQuery"]()) && (ctx.uc1 = _t.first);
39+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵloadQuery"]()) && (ctx.uc2 = _t.first);
40+
} }, features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]], decls: 1, vars: 1, consts: [[4, "ngIf"], ["uc2", ""]], template: function Example4Component_Template(rf, ctx) { if (rf & 1) {
41+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵtemplate"](0, Example4Component_div_0_Template, 4, 0, "div", 0);
42+
} if (rf & 2) {
43+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵproperty"]("ngIf", true);
44+
} }, directives: [_angular_common__WEBPACK_IMPORTED_MODULE_2__["NgIf"]], styles: ["... */"] });
45+
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](Example4Component, [{
46+
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Component"],
47+
args: [{
48+
selector: 'app-example4',
49+
templateUrl: './example4.component.html',
50+
styleUrls: ['../example1/example1.component.sass']
51+
}]
52+
}], function () { return []; }, { uc1: [{
53+
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewChild"],
54+
args: ['uc1', { static: true }]
55+
}], uc2: [{
56+
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewChild"],
57+
args: ['uc2', { static: true }]
58+
}] }); })();
59+
60+
61+
/***/ }),
62+
```
63+
64+
```javascript
65+
// Static is set to False
66+
const _c0 = ["uc1"];
67+
const _c1 = ["uc2"];
68+
function Example4Component_div_0_Template(rf, ctx) { if (rf & 1) {
69+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵelementStart"](0, "div", null, 1);
70+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵelementStart"](2, "p");
71+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵtext"](3, "My amazing content !");
72+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵelementEnd"]();
73+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵelementEnd"]();
74+
} }
75+
class Example4Component extends _app_example1_a_component__WEBPACK_IMPORTED_MODULE_1__["AComponent"] {
76+
constructor() {
77+
super();
78+
// this.printRef.push(() => this.uc1);
79+
this.printRef.push(() => this.uc2);
80+
}
81+
}
82+
Example4Component.ɵfac = function Example4Component_Factory(t) { return new (t || Example4Component)(); };
83+
Example4Component.ɵcmp = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineComponent"]({ type: Example4Component, selectors: [["app-example4"]], viewQuery: function Example4Component_Query(rf, ctx) { if (rf & 1) {
84+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵstaticViewQuery"](_c0, true);
85+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵviewQuery"](_c1, true);
86+
} if (rf & 2) {
87+
var _t;
88+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵloadQuery"]()) && (ctx.uc1 = _t.first);
89+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵloadQuery"]()) && (ctx.uc2 = _t.first);
90+
} }, features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]], decls: 1, vars: 1, consts: [[4, "ngIf"], ["uc2", ""]], template: function Example4Component_Template(rf, ctx) { if (rf & 1) {
91+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵtemplate"](0, Example4Component_div_0_Template, 4, 0, "div", 0);
92+
} if (rf & 2) {
93+
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵproperty"]("ngIf", true);
94+
} }, directives: [_angular_common__WEBPACK_IMPORTED_MODULE_2__["NgIf"]], styles: ["..."] });
95+
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](Example4Component, [{
96+
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Component"],
97+
args: [{
98+
selector: 'app-example4',
99+
templateUrl: './example4.component.html',
100+
styleUrls: ['../example1/example1.component.sass']
101+
}]
102+
}], function () { return []; }, { uc1: [{
103+
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewChild"],
104+
args: ['uc1', { static: true }]
105+
}], uc2: [{
106+
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewChild"],
107+
args: ['uc2', { static: false }]
108+
}] }); })();
109+
110+
111+
/***/ }),
112+
```
113+
114+
## ViewChild Read attribute ([link](https://angular.io/api/core/ViewChild))
115+
116+
The ViewChild Read attribute allow you to read a different token from the queried elements.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<pre>
2+
<h4>Template Reminder</h4>
3+
4+
> UC 1 static=False
5+
<div #uc1>
6+
<p>My amazing content !</p>
7+
</div>
8+
9+
> UC 2 static=False/True
10+
<div #uc2 *ngIf="true">
11+
<p>My amazing content !</p>
12+
</div>
13+
14+
> UC 3 read attribute HTML Element
15+
<div #uc3>
16+
<p>My amazing content !</p>
17+
</div>
18+
19+
> UC 4 read attribute Component
20+
<app-simple-content #uc4>
21+
<p>My amazing content !</p>
22+
</app-simple-content>
23+
24+
> UC 5 read attribute Component - ElementRef
25+
<app-simple-content #uc5>
26+
<p>My amazing content !</p>
27+
</app-simple-content>
28+
29+
> UC 6 read attribute Component - ViewContainerRef
30+
<app-simple-content #uc6>
31+
<p>My amazing content !</p>
32+
</app-simple-content>
33+
34+
> UC 7 read attribute Component - ViewRef
35+
<app-simple-content #uc7>
36+
<p>My amazing content !</p>
37+
</app-simple-content>
38+
</pre>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Component, ViewChild, ElementRef, ViewContainerRef, ComponentRef, ViewRef } from '@angular/core';
2+
import { AComponent } from '@app/example1/a-component';
3+
4+
@Component({
5+
selector: 'app-example4',
6+
templateUrl: './example4.component.html',
7+
styleUrls: ['../example1/example1.component.sass']
8+
})
9+
export class Example4Component extends AComponent {
10+
// Static Attribute Use Case
11+
@ViewChild('uc1', { static: true }) uc1: ElementRef;
12+
@ViewChild('uc2', { static: false }) uc2: ElementRef; // Default value is False
13+
14+
// Read Attribute Use Case
15+
@ViewChild('uc3', { static: true }) uc3: any;
16+
@ViewChild('uc4', { static: true }) uc4: any;
17+
@ViewChild('uc5', { read: ElementRef, static: true }) uc5: any;
18+
@ViewChild('uc6', { read: ViewContainerRef, static: true }) uc6: any;
19+
@ViewChild('uc7', { read: ViewRef, static: true }) uc7: any; // <-- ViewRef cannot be returned from the DOM and have to be constructed manually.
20+
21+
constructor() {
22+
super();
23+
24+
// Static Attribute Use Case
25+
this.printRef.push(() => this.uc1);
26+
this.printRef.push(() => this.uc2);
27+
}
28+
29+
// Read Attribute Use Case
30+
ngOnInit() {
31+
console.log(' > UC3 ', this.uc3);
32+
console.log(' > UC4 ', this.uc4);
33+
console.log(' > UC5 ', this.uc5);
34+
console.log(' > UC6 ', this.uc6);
35+
console.log(' > UC7 ', this.uc7);
36+
}
37+
}

src/app/example4/example4.module.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { NgModule } from '@angular/core';
2+
import { CommonModule } from '@angular/common';
3+
import { Example4Component } from './example4.component';
4+
import { SimpleContentComponent } from './simple-content/simple-content.component';
5+
6+
7+
8+
@NgModule({
9+
declarations: [Example4Component, SimpleContentComponent],
10+
exports: [Example4Component, SimpleContentComponent],
11+
imports: [
12+
CommonModule
13+
]
14+
})
15+
export class Example4Module { }
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Component } from '@angular/core';
2+
3+
@Component({
4+
selector: 'app-simple-content',
5+
template: `<ng-content></ng-content>`,
6+
styles: []
7+
})
8+
export class SimpleContentComponent {
9+
constructor() { }
10+
}

src/app/sandbox/sandbox.component.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@
77
<app-example2></app-example2>
88

99
<!-- Dynamic contents - Full -->
10-
<app-example3></app-example3>
10+
<app-example3></app-example3>
11+
<!-- ViewChild read / static attribute -->
12+
<app-example4></app-example4>

src/app/sandbox/sandbox.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { SandboxComponent } from './sandbox.component';
55
import { Example1Module } from '@app/example1/example1.module';
66
import { Example2Module } from '@app/example2/example2.module';
77
import { Example3Module } from '@app/example3/example3.module';
8+
import { Example4Module } from '@app/example4/example4.module';
89

910
@NgModule({
1011
declarations: [SandboxComponent],
@@ -13,7 +14,8 @@ import { Example3Module } from '@app/example3/example3.module';
1314
CommonModule,
1415
Example1Module,
1516
Example2Module,
16-
Example3Module
17+
Example3Module,
18+
Example4Module
1719
]
1820
})
1921
export class SandboxModule { }

0 commit comments

Comments
 (0)