Skip to content

Commit

Permalink
Merge pull request #1 from GenesisTMS/update-lifecycle-hooks
Browse files Browse the repository at this point in the history
migrate: update lifecycle hooks
  • Loading branch information
GZGavinZhao authored Jun 18, 2022
2 parents e0ed3c0 + 4c22472 commit 7500853
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 86 deletions.
4 changes: 2 additions & 2 deletions lib/app_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import 'src/after_content_component.dart';
import 'src/after_view_component.dart';
import 'src/counter_component.dart';
import 'src/do_check_component.dart';
import 'src/on_changes_component.dart';
import 'src/after_changes_component.dart';
import 'src/peek_a_boo_parent_component.dart';
import 'src/spy_component.dart';

Expand All @@ -16,7 +16,7 @@ import 'src/spy_component.dart';
AfterViewParentComponent,
CounterParentComponent,
DoCheckParentComponent,
OnChangesParentComponent,
AfterChangesParentComponent,
PeekABooParentComponent,
SpyParentComponent,
],
Expand Down
8 changes: 4 additions & 4 deletions lib/app_component.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<a id="top"></a>
<h1>Component Lifecycle Hooks</h1>
<a href="#hooks">Peek-a-boo: (most) lifecycle hooks</a><br>
<a href="#onchanges">OnChanges</a><br>
<a href="#afterchanges">AfterChanges</a><br>
<a href="#docheck">DoCheck</a><br>
<a href="#after-view">AfterViewInit & AfterViewChecked</a><br>
<a href="#after-content">AfterContentInit & AfterContentChecked</a><br>
<a href="#spy">Spy: directive with OnInit & OnDestroy</a><br>
<a href="#counter">Counter: OnChanges + Spy directive</a><br>
<a href="#counter">Counter: AfterChanges + Spy directive</a><br>

<a id="hooks"></a>
<peek-a-boo-parent></peek-a-boo-parent>
Expand All @@ -16,8 +16,8 @@ <h1>Component Lifecycle Hooks</h1>
<spy-parent></spy-parent>
<a href="#top">back to top</a>

<a id="onchanges"></a>
<on-changes-parent></on-changes-parent>
<a id="afterchanges"></a>
<after-changes-parent></after-changes-parent>
<a href="#top">back to top</a>

<a id="docheck"></a>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import 'dart:convert';

import 'package:angular/angular.dart';
import 'package:angular_forms/angular_forms.dart';

Expand All @@ -10,10 +8,10 @@ class Hero {
}

@Component(
selector: 'on-changes',
selector: 'after-changes',
template: '''
<div class="hero">
<p>{{hero.name}} can {{power}}</p>
<div *ngIf="hero != null" class="hero">
<p>{{hero!.name}} can {{power}}</p>
<h4>-- Change Log --</h4>
<div *ngFor="let chg of changeLog">{{chg}}</div>
Expand All @@ -25,47 +23,41 @@ class Hero {
],
directives: [coreDirectives],
)
class OnChangesComponent implements OnChanges {
class AfterChangesComponent implements AfterChanges {
// #docregion inputs
@Input()
Hero hero;
Hero? hero;
@Input()
String power;
String power = '';
// #enddocregion inputs

List<String> changeLog = [];

// #docregion ng-on-changes
ngOnChanges(Map<String, SimpleChange> changes) {
changes.forEach((String propName, SimpleChange change) {
String cur = json.encode(change.currentValue);
String prev = change.previousValue == null
? "{}"
: json.encode(change.previousValue);
changeLog.add('$propName: currentValue = $cur, previousValue = $prev');
});
// #docregion ng-after-changes
ngAfterChanges() {
changeLog.add('Input property has changed. ($power)');
}
// #enddocregion ng-on-changes
// #enddocregion ng-after-changes

void reset() {
changeLog.clear();
}
}

@Component(
selector: 'on-changes-parent',
templateUrl: 'on_changes_parent_component.html',
selector: 'after-changes-parent',
templateUrl: 'after_changes_parent_component.html',
styles: ['.parent {background: Lavender}'],
directives: [coreDirectives, formDirectives, OnChangesComponent],
directives: [coreDirectives, formDirectives, AfterChangesComponent],
)
class OnChangesParentComponent {
Hero hero;
String power;
String title = 'OnChanges';
@ViewChild(OnChangesComponent)
OnChangesComponent childView;
class AfterChangesParentComponent {
late Hero hero;
late String power;
String title = 'AfterChanges';
@ViewChild(AfterChangesComponent)
AfterChangesComponent? childView;

OnChangesParentComponent() {
AfterChangesParentComponent() {
reset();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ <h2>{{title}}</h2>
</table>
<p><button (click)="reset()">Reset Log</button></p>

<!-- #docregion on-changes -->
<on-changes [hero]="hero" [power]="power"></on-changes>
<!-- #enddocregion on-changes -->
<!-- #docregion after-changes -->
<after-changes [hero]="hero" [power]="power"></after-changes>
<!-- #enddocregion after-changes -->
</div>
7 changes: 4 additions & 3 deletions lib/src/after_content_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ class ChildComponent {
)
// #docregion hooks
class AfterContentComponent implements AfterContentChecked, AfterContentInit {
String _prevHero = '';
String? _prevHero = '';
String comment = '';

// Query for a CONTENT child of type `ChildComponent`
@ContentChild(ChildComponent)
ChildComponent contentChild;
ChildComponent? contentChild;

// #enddocregion hooks
final LoggerService _logger;
Expand Down Expand Up @@ -64,7 +64,8 @@ class AfterContentComponent implements AfterContentChecked, AfterContentInit {
// #docregion do-something
/// This surrogate for real business logic; sets the `comment`
void _doSomething() {
comment = contentChild.hero.length > 10 ? "That's a long name" : '';
final length = contentChild?.hero.length ?? 0;
comment = length > 10 ? "That's a long name" : '';
}
// #enddocregion do-something

Expand Down
11 changes: 6 additions & 5 deletions lib/src/after_view_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ class ChildViewComponent {
)
// #docregion hooks
class AfterViewComponent implements AfterViewChecked, AfterViewInit {
var _prevHero = '';
String? _prevHero = '';

// Query for a VIEW child of type `ChildViewComponent`
@ViewChild(ChildViewComponent)
ChildViewComponent viewChild;
ChildViewComponent? viewChild;

// #enddocregion hooks
final LoggerService _logger;
Expand All @@ -51,10 +51,10 @@ class AfterViewComponent implements AfterViewChecked, AfterViewInit {

ngAfterViewChecked() {
// viewChild is updated after the view has been checked
if (_prevHero == viewChild.hero) {
if (_prevHero == viewChild?.hero) {
_logIt('AfterViewChecked (no change)');
} else {
_prevHero = viewChild.hero;
_prevHero = viewChild?.hero;
_logIt('AfterViewChecked');
_doSomething();
}
Expand All @@ -66,7 +66,8 @@ class AfterViewComponent implements AfterViewChecked, AfterViewInit {
// #docregion do-something
// This surrogate for real business logic sets the `comment`
void _doSomething() {
var c = viewChild.hero.length > 10 ? "That's a long name" : '';
var length = viewChild?.hero.length ?? 0;
var c = length > 10 ? "That's a long name" : '';
if (c != comment) {
// Wait a tick because the component's view has already been checked
_logger.tick().then((_) {
Expand Down
15 changes: 6 additions & 9 deletions lib/src/counter_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,20 @@ import 'spy_directive.dart';
styles: ['.counter {background: LightYellow; padding: 8px; margin-top: 8px}'],
directives: [coreDirectives, SpyDirective],
)
class MyCounterComponent implements OnChanges {
class MyCounterComponent implements AfterChanges {
@Input()
num counter;
num counter = 0;
List<String> changeLog = [];

ngOnChanges(Map<String, SimpleChange> changes) {
ngAfterChanges() {
// Empty the changeLog whenever counter goes to zero
// hint: this is a way to respond programmatically to external value changes.
if (this.counter == 0) {
changeLog.clear();
}

// A change to `counter` is the only change we care about
SimpleChange chng = changes['counter'];
var cur = chng.currentValue;
var prev = chng.previousValue == null ? "{}" : chng.previousValue;
changeLog.add('counter: currentValue = $cur, previousValue = $prev');
// A change to `counter` is the only change we can get.
changeLog.add('counter changed to $counter');
}
}

Expand All @@ -57,7 +54,7 @@ class MyCounterComponent implements OnChanges {
)
class CounterParentComponent {
final LoggerService _logger;
num value;
num value = 0;

CounterParentComponent(this._logger) {
reset();
Expand Down
21 changes: 11 additions & 10 deletions lib/src/do_check_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ class Hero {
@Component(
selector: 'do-check',
template: '''
<div class="hero">
<p>{{hero.name}} can {{power}}</p>
<div *ngIf="hero != null" class="hero">
<p>{{hero!.name}} can {{power}}</p>
<h4>-- Change Log --</h4>
<div *ngFor="let chg of changeLog">{{chg}}</div>
Expand All @@ -25,9 +25,9 @@ class Hero {
)
class DoCheckComponent implements DoCheck {
@Input()
Hero hero;
Hero? hero;
@Input()
String power;
String power = '';

bool changeDetected = false;
List<String> changeLog = [];
Expand All @@ -39,11 +39,12 @@ class DoCheckComponent implements DoCheck {

// #docregion ng-do-check
ngDoCheck() {
if (hero.name != oldHeroName) {
final heroName = hero?.name ?? '';
if (heroName != oldHeroName) {
changeDetected = true;
changeLog.add(
'DoCheck: Hero name changed to "${hero.name}" from "$oldHeroName"');
oldHeroName = hero.name;
'DoCheck: Hero name changed to "${heroName}" from "$oldHeroName"');
oldHeroName = heroName;
}

if (power != oldPower) {
Expand Down Expand Up @@ -87,11 +88,11 @@ class DoCheckComponent implements DoCheck {
directives: [coreDirectives, formDirectives, DoCheckComponent],
)
class DoCheckParentComponent {
Hero hero;
String power;
late Hero hero;
late String power;
String title = 'DoCheck';
@ViewChild(DoCheckComponent)
DoCheckComponent childView;
DoCheckComponent? childView;

DoCheckParentComponent() {
reset();
Expand Down
21 changes: 5 additions & 16 deletions lib/src/peek_a_boo_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class PeekABoo implements OnInit {
// unless we want typing and tool support.
class PeekABooComponent extends PeekABoo
implements
OnChanges,
AfterChanges,
OnInit,
DoCheck,
AfterContentInit,
Expand All @@ -42,31 +42,20 @@ class PeekABooComponent extends PeekABoo
AfterViewChecked,
OnDestroy {
@Input()
String name;
String? name;

int _afterContentCheckedCounter = 1;
int _afterViewCheckedCounter = 1;
int _onChangesCounter = 1;
String _verb = 'initialized';
int _afterChangesCounter = 1;

PeekABooComponent(LoggerService logger) : super(logger) {
var _is = name != null ? 'is' : 'is not';
_logIt('name $_is known at construction');
}

// Only called if there is an @input variable set by parent.
void ngOnChanges(Map<String, SimpleChange> changes) {
List<String> messages = [];
changes.forEach((String propName, SimpleChange change) {
if (propName == 'name') {
var name = changes['name'].currentValue;
messages.add('name $_verb to "$name"');
} else {
messages.add('$propName $_verb');
}
});
_logIt('OnChanges (${_onChangesCounter++}): ${messages.join('; ')}');
_verb = 'changed'; // Next time it will be a change
void ngAfterChanges() {
_logIt('AfterChanges (${_afterChangesCounter++})');
}

// Beware! Called frequently!
Expand Down
14 changes: 8 additions & 6 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ description: Lifecycle Hooks
version: 0.0.1

environment:
sdk: '>=2.5.0 <3.0.0'
sdk: '>=2.12.0 <3.0.0'

dependencies:
angular: ^6.0.1
angular_forms: ^3.0.0
angular: ^7.0.2
angular_forms: ^4.0.1

dev_dependencies:
build_runner: ^1.7.0
build_test: ^1.3.6
build_web_compilers: ^2.4.0
build_runner: ^2.1.8
build_test: ^2.1.5
test: ^1.20.0
build_web_compilers: ^3.2.2
angular_test: ^4.0.1
Loading

0 comments on commit 7500853

Please sign in to comment.