Skip to content
Angular ng getting-started 4 min read

What is Angular?

Angular is a component-based TypeScript framework for building scalable single-page web applications, developed and maintained by Google. Unlike a thin UI library, Angular ships with everything a real application needs out of the box: a component model, a powerful template syntax, dependency injection, routing, forms, and an HTTP client. This page introduces what Angular is, what it is used for, and how the modern framework (v17 and later) differs from the legacy AngularJS it replaced.

A complete, opinionated framework

Where some tools hand you only a rendering primitive and leave the rest to the ecosystem, Angular is a framework: it provides a structured, batteries-included platform with official, well-integrated answers to the common problems of app development. Routing, form handling, HTTP communication, and dependency injection all ship as first-party packages designed to work together.

That structure is the trade-off. Angular is more opinionated and has a larger initial surface area than a minimal library, but in return large teams get consistency, strong tooling, and conventions that keep big codebases maintainable. Everything is written in TypeScript, so you get static types, autocompletion, and refactoring safety across the whole stack.

Components and templates

The building block of every Angular app is the component: a TypeScript class paired with an HTML template and styles. Modern Angular uses standalone components by default — components declare their own dependencies via the imports array, so the old NgModule boilerplate is no longer required.

import { Component } from '@angular/core';

@Component({
  selector: 'app-greeting',
  standalone: true,
  template: `<h1>Hello, {{ name }}!</h1>`,
})
export class GreetingComponent {
  name = 'Ada';
}

The {{ name }} syntax is interpolation — it binds the class property into the rendered DOM. When name changes, Angular updates the view for you; you never touch the DOM by hand.

Signals: modern reactivity

Recent Angular introduces signals, a fine-grained reactive primitive for holding and deriving state. A signal is a value you read by calling it, and templates that read a signal update automatically when it changes.

import { Component, signal, computed } from '@angular/core';

@Component({
  selector: 'app-counter',
  standalone: true,
  template: `
    <p>Count: {{ count() }} — doubled: {{ doubled() }}</p>
    <button (click)="increment()">Increment</button>
  `,
})
export class CounterComponent {
  count = signal(0);
  doubled = computed(() => this.count() * 2);

  increment() {
    this.count.update((n) => n + 1);
  }
}

(click) is event binding, and computed() derives a value that recalculates only when its dependencies change — the foundation of efficient, predictable updates in modern Angular.

The new control flow syntax

Modern templates use built-in control flow blocks@if, @for, and @switch — which replace the older *ngIf and *ngFor structural directives. The new syntax is faster, type-checked, and needs no imports.

@if (user(); as u) {
  <p>Welcome back, {{ u.name }}</p>
} @else {
  <p>Please sign in</p>
}

<ul>
  @for (item of items(); track item.id) {
    <li>{{ item.label }}</li>
  } @empty {
    <li>No items yet</li>
  }
</ul>

The mandatory track expression tells Angular how to identify items, so list updates reuse DOM nodes efficiently instead of re-rendering the whole list.

Dependency injection and services

Angular has a built-in dependency injection system. Shared logic lives in services, which components request rather than construct. The modern inject() function makes this concise and works in functional guards and interceptors too.

import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class UserService {
  private http = inject(HttpClient);

  getUsers() {
    return this.http.get<User[]>('/api/users');
  }
}

providedIn: 'root' registers a single shared instance app-wide, so any component can inject(UserService) and get the same object.

Modern Angular vs legacy AngularJS

AngularJS (version 1.x, released in 2010) and Angular (the complete rewrite from version 2 onward) are different frameworks that share only a name. New projects should always use modern Angular.

AspectAngularJS (1.x)Modern Angular (17+)
LanguageJavaScriptTypeScript
ArchitectureControllers, $scope, directivesStandalone components
ReactivityDirty-checking digest cycleSignals + zoneless option
Templatesng-if, ng-repeat@if, @for, @switch
Module systemCustom DI modulesES modules + standalone APIs
ToolingManual / BowerAngular CLI + esbuild
StatusEnd of lifeActively developed

Note: “Angular” with no version number always means the modern framework. The name “AngularJS” refers only to the deprecated 1.x line, which reached end of life in 2022.

What you can build

Because Angular bundles routing, forms, and HTTP support, it suits ambitious, long-lived applications:

  • Enterprise single-page applications — dashboards, admin consoles, and internal tools with complex state.
  • Progressive web apps — installable, offline-capable apps using the official service-worker package.
  • Server-side rendered sites — fast, SEO-friendly pages via Angular SSR and hydration.
  • Large multi-team codebases — where strong conventions and TypeScript keep growth manageable.

Best practices

  • Start every new project with standalone components and skip NgModule entirely.
  • Use signals and computed() for component state instead of manual change-detection juggling.
  • Prefer the new @if / @for / @switch control flow over the legacy *ngIf / *ngFor directives, and always provide a track expression in @for.
  • Inject dependencies with inject() and keep shared logic in providedIn: 'root' services.
  • Write everything in TypeScript with strict mode enabled to catch errors at compile time.
  • Lean on the Angular CLI for scaffolding, building, and testing rather than hand-wiring tooling.
Last updated June 14, 2026
Was this helpful?