ng-init was a directive from AngularJS (version 1.x, the original framework before the complete rewrite into modern Angular 2+) used for initializing a scope variable directly in a template — it has no direct equivalent in modern Angular, which handles initialization through component lifecycle hooks instead.
The old AngularJS pattern
{{ currentUser }} has {{ itemCount }} items
This ran inline in the template itself, directly setting scope variables as the element initialized — a pattern that modern Angular's component-based, TypeScript-first architecture doesn't support or need in the same way.
The modern Angular replacement: ngOnInit
@Component({
selector: 'app-user-profile',
template: `{{ currentUser }} has {{ itemCount }} items`
})
export class UserProfileComponent implements OnInit {
currentUser: string = '';
itemCount: number = 0;
ngOnInit(): void {
this.currentUser = 'Alex';
this.itemCount = 0;
}
}
ngOnInit() runs once, after Angular has initialized the component's inputs and bindings — the standard, structured place for initialization logic that ng-init handled inline in the older framework.
Initializing directly in property declarations, for simple static values
export class UserProfileComponent {
currentUser: string = 'Alex';
itemCount: number = 0;
}
For values that don't depend on any async data or injected service, initializing directly at property declaration is simpler than using ngOnInit() at all — reaching for the lifecycle hook specifically makes sense once initialization needs to happen after dependency injection or requires calling a service.
Initializing from an injected service
export class UserProfileComponent implements OnInit {
currentUser: string = '';
constructor(private userService: UserService) {}
ngOnInit(): void {
this.currentUser = this.userService.getCurrentUserName();
}
}
This is exactly the kind of initialization ng-init couldn't have handled even in AngularJS — it required a genuinely simple, static value expressible directly in template syntax, whereas ngOnInit() can run arbitrary component logic, including calling injected services.
Why the shift away from template-based logic happened
AngularJS's template directives like ng-init mixed logic directly into HTML markup, which became difficult to test, trace, and maintain as applications grew — modern Angular's deliberate separation, keeping logic in TypeScript component classes and templates focused on presentation, was a core architectural decision in the framework's complete rewrite, not just a naming change.
If you encounter ng-init in an old codebase or tutorial
Seeing ng-init in any code sample is a reliable signal that the sample is written for AngularJS (1.x), not modern Angular (2 and later, including the current versions) — despite the similar name, these are genuinely different frameworks with incompatible syntax, and AngularJS-era tutorials generally shouldn't be followed directly for a modern Angular project.