Lifecycle Hooks Examples
This page demonstrates AngularDart lifecycle hooks with practical examples.
Example 1: Data Loading with OnInit
Load data when the component initializes:
import 'package:angulardart/angular.dart';
@Component(
selector: 'user-list',
template: '<div *ngIf="isLoading">Loading users...</div>'
'<ul *ngIf="!isLoading">'
'<li *ngFor="let user of users">{{ user.name }}</li>'
'</ul>',
)
class UserListComponent implements OnInit {
List<User> users = [];
bool isLoading = true;
final UserService _userService;
UserListComponent(this._userService);
@override
void ngOnInit() {
_userService.getUsers().then((data) {
users = data;
isLoading = false;
});
}
}
Example 2: Cleanup with OnDestroy
Clean up resources when the component is destroyed:
@Component(
selector: 'live-clock',
template: '<p>Current time: {{ currentTime }}</p>',
)
class LiveClockComponent implements OnDestroy {
String currentTime = '';
late final Timer _timer;
LiveClockComponent() {
_updateTime();
_timer = Timer.periodic(Duration(seconds: 1), (_) => _updateTime());
}
void _updateTime() {
currentTime = DateTime.now().toIso8601String();
}
@override
void ngOnDestroy() {
_timer.cancel();
}
}
Example 3: Reactive Changes with OnChanges
React to input changes:
@Component(
selector: 'search-results',
template: '<div *ngIf="hasSearchChanged">'
'<p>Searching for: {{ query }}</p>'
'<div *ngIf="isLoading">Searching...</div>'
'<ul *ngIf="!isLoading">'
'<li *ngFor="let result of results">{{ result.title }}</li>'
'</ul>'
'</div>',
)
class SearchResultsComponent implements OnChanges {
@Input()
String query = '';
List<SearchResult> results = [];
bool isLoading = false;
bool hasSearchChanged = false;
final SearchService _searchService;
SearchResultsComponent(this._searchService);
@override
void ngOnChanges(SimpleChanges changes) {
if (changes.containsKey('query') && !changes['query']!.isFirstChange()) {
hasSearchChanged = true;
isLoading = true;
_searchService.search(query).then((data) {
results = data;
isLoading = false;
});
}
}
}
Example 4: View Access with AfterViewInit
Access child elements after the view is initialized:
@Component(
selector: 'chart-container',
template: '<div #chartContainer class="chart"></div>'
'<button (click)="resetChart()">Reset</button>',
)
class ChartContainerComponent implements AfterViewInit {
@ViewChild('chartContainer')
HtmlElement? chartContainer;
Chart? _chart;
@override
void ngAfterViewInit() {
_initializeChart();
}
void _initializeChart() {
if (chartContainer != null) {
_chart = Chart(chartContainer!, {
'type': 'bar',
'data': {/* ... */},
});
}
}
void resetChart() {
_chart?.reset();
}
}
Example 5: Content Projection with AfterContentInit
Work with projected content:
@Component(
selector: 'tab-container',
template: '<div class="tabs">'
'<ng-content select="[tab-label]"></ng-content>'
'</div>'
'<div class="tab-content">'
'<ng-content select="[tab-panel]"></ng-content>'
'</div>',
)
class TabContainerComponent implements AfterContentInit {
@ContentChildren(TabLabelDirective)
List<TabLabelDirective>? labels;
@override
void ngAfterContentInit() {
// Initialize tabs after content is projected
labels?.first.isActive = true;
}
}
Example 6: Custom Change Detection with DoCheck
Implement custom change detection:
@Component(
selector: 'item-counter',
template: '<p>Items: {{ items.length }}</p>'
'<p *ngIf="hasChanged">List was modified!</p>',
)
class ItemCounterComponent implements DoCheck {
@Input()
List<String> items = [];
int _previousLength = 0;
bool hasChanged = false;
@override
void ngDoCheck() {
if (items.length != _previousLength) {
hasChanged = true;
_previousLength = items.length;
// Reset after a delay
Future.delayed(Duration(seconds: 2), () => hasChanged = false);
}
}
}
Example 7: Complete Lifecycle Demo
@Component(
selector: 'lifecycle-demo',
template: '<p>Check console for lifecycle output</p>',
)
class LifecycleDemoComponent
implements OnInit, OnChanges, DoCheck, OnDestroy,
AfterContentInit, AfterContentChecked,
AfterViewInit, AfterViewChecked {
@Input()
String? name;
int _doCheckCount = 0;
int _viewCheckCount = 0;
int _contentCheckCount = 0;
LifecycleDemoComponent() {
print('Constructor called');
}
@override
void ngOnChanges(SimpleChanges changes) {
print('ngOnChanges: $changes');
}
@override
void ngOnInit() {
print('ngOnInit');
}
@override
void ngDoCheck() {
_doCheckCount++;
if (_doCheckCount <= 3) {
print('ngDoCheck (#$_doCheckCount)');
}
}
@override
void ngAfterContentInit() {
print('ngAfterContentInit');
}
@override
void ngAfterContentChecked() {
_contentCheckCount++;
if (_contentCheckCount <= 3) {
print('ngAfterContentChecked (#$_contentCheckCount)');
}
}
@override
void ngAfterViewInit() {
print('ngAfterViewInit');
}
@override
void ngAfterViewChecked() {
_viewCheckCount++;
if (_viewCheckCount <= 3) {
print('ngAfterViewChecked (#$_viewCheckCount)');
}
}
@override
void ngOnDestroy() {
print('ngOnDestroy');
}
}