Key Features of Angular

1. Component-Based Architecture

Angular’s architecture is built around components, which are the fundamental building blocks of Angular applications.

// Example of a component with different features
@Component({
  selector: 'app-user-profile',
  template: `
    <div class="profile-card">
      <h2>{{ user.name | titlecase }}</h2>
      <p>{{ user.bio }}</p>
      <button (click)="updateProfile()">Update</button>
    </div>
  `,
  styles: [`
    .profile-card {
      padding: 1rem;
      border: 1px solid #ddd;
      border-radius: 8px;
    }
  `]
})
export class UserProfileComponent implements OnInit {
  user = { name: '', bio: '' };

  ngOnInit() {
    this.loadUserProfile();
  }

  loadUserProfile() {
    // Load user data
  }
}

2. TypeScript Integration

Angular is built with TypeScript, providing strong typing, object-oriented features, and compile-time error checking.

// Interface definition
interface User {
  id: number;
  name: string;
  email: string;
  role: 'admin' | 'user';
  lastLogin?: Date;
}

// Service with TypeScript
@Injectable({
  providedIn: 'root'
})
class UserService {
  private users: User[] = [];

  getUser(id: number): User | undefined {
    return this.users.find(user => user.id === id);
  }

  addUser(user: Omit<User, 'id'>): User {
    const newUser = { ...user, id: this.generateId() };
    this.users.push(newUser);
    return newUser;
  }
}

3. Dependency Injection (DI)

Angular’s DI system helps manage component dependencies and enables better testing and modularity.

// Service definition
@Injectable({
  providedIn: 'root'
})
class LoggerService {
  log(message: string) {
    console.log(`[${new Date().toISOString()}]: ${message}`);
  }
}

// Using the service in a component
@Component({
  selector: 'app-example'
})
class ExampleComponent {
  constructor(
    private logger: LoggerService,
    private userService: UserService
  ) {}

  performAction() {
    this.logger.log('Action performed');
    // Use userService
  }
}

4. Powerful Template System

Angular’s template syntax provides powerful features for building dynamic UIs.

@Component({
  selector: 'app-todo-list',
  template: `
    <!-- Event Binding -->
    <button (click)="addTask()">Add Task</button>

    <!-- Property Binding -->
    <input [value]="newTask" (input)="newTask = $event.target.value">

    <!-- Structural Directives -->
    <ul>
      <li *ngFor="let task of tasks; let i = index">
        <!-- Two-way Binding -->
        <input [(ngModel)]="tasks[i]">
        
        <!-- Event with Parameter -->
        <button (click)="removeTask(i)">Delete</button>
      </li>
    </ul>

    <!-- Conditional Rendering -->
    <p *ngIf="tasks.length === 0">No tasks available</p>
  `
})
class TodoListComponent {
  tasks: string[] = [];
  newTask = '';

  addTask() {
    if (this.newTask.trim()) {
      this.tasks.push(this.newTask);
      this.newTask = '';
    }
  }

  removeTask(index: number) {
    this.tasks.splice(index, 1);
  }
}

5. Forms and Validation

Angular provides two types of forms: Template-driven and Reactive forms.

// Reactive Form Example
@Component({
  selector: 'app-registration',
  template: `
    <form [formGroup]="registrationForm" (ngSubmit)="onSubmit()">
      <div>
        <input formControlName="email" placeholder="Email">
        <div *ngIf="email.invalid && email.touched" class="error">
          <span *ngIf="email.errors?.['required']">Email is required</span>
          <span *ngIf="email.errors?.['email']">Invalid email format</span>
        </div>
      </div>

      <div>
        <input formControlName="password" type="password" placeholder="Password">
        <div *ngIf="password.invalid && password.touched" class="error">
          <span *ngIf="password.errors?.['minlength']">
            Password must be at least 8 characters
          </span>
        </div>
      </div>

      <button type="submit" [disabled]="registrationForm.invalid">
        Register
      </button>
    </form>
  `
})
class RegistrationComponent {
  registrationForm = new FormGroup({
    email: new FormControl('', [Validators.required, Validators.email]),
    password: new FormControl('', [
      Validators.required,
      Validators.minLength(8)
    ])
  });

  get email() { return this.registrationForm.get('email')!; }
  get password() { return this.registrationForm.get('password')!; }

  onSubmit() {
    if (this.registrationForm.valid) {
      console.log(this.registrationForm.value);
    }
  }
}

6. HTTP Client

Angular provides a powerful HTTP client for making API calls.

@Injectable({
  providedIn: 'root'
})
class ApiService {
  constructor(private http: HttpClient) {}

  // GET request with type safety
  getUsers(): Observable<User[]> {
    return this.http.get<User[]>('/api/users').pipe(
      retry(3),
      catchError(this.handleError)
    );
  }

  // POST request with body
  createUser(user: Omit<User, 'id'>): Observable<User> {
    return this.http.post<User>('/api/users', user).pipe(
      catchError(this.handleError)
    );
  }

  private handleError(error: HttpErrorResponse) {
    console.error('An error occurred:', error.message);
    return throwError(() => 
      new Error('Something went wrong; please try again later.'));
  }
}

7. Routing and Navigation

Angular’s router enables navigation between views.

// Route configuration
const routes: Routes = [
  {
    path: 'users',
    component: UserListComponent,
    children: [
      { path: ':id', component: UserDetailComponent }
    ],
    canActivate: [AuthGuard]
  },
  {
    path: 'admin',
    loadChildren: () => 
      import('./admin/admin.module').then(m => m.AdminModule),
    canLoad: [AdminGuard]
  }
];

// Using router in components
@Component({
  template: `
    <nav>
      <a routerLink="/users" routerLinkActive="active">Users</a>
      <a [routerLink]="['/users', userId]">User Details</a>
    </nav>
    <router-outlet></router-outlet>
  `
})
class AppComponent {
  constructor(private router: Router) {}

  navigateToUser(id: number) {
    this.router.navigate(['/users', id], {
      queryParams: { tab: 'profile' }
    });
  }
}

8. Standalone Components (Modern Angular)

Angular’s standalone components provide a simpler way to build applications.

// Standalone component
@Component({
  standalone: true,
  selector: 'app-feature',
  imports: [
    CommonModule,
    RouterModule,
    SharedComponentsModule
  ],
  template: `
    <div>
      <h1>{{ title }}</h1>
      <shared-component></shared-component>
    </div>
  `
})
export class FeatureComponent {
  title = 'Feature Component';
}

// Bootstrap standalone application
bootstrapApplication(AppComponent, {
  providers: [
    provideRouter(routes),
    provideHttpClient(),
    provideAnimations()
  ]
}).catch(err => console.error(err));

Interview Tips

When discussing Angular’s key features in an interview:

  1. Emphasize Modern Features:

    • Highlight standalone components
    • Discuss performance improvements
    • Mention modern development practices
  2. Real-world Applications:

    • Explain how features solve common problems
    • Share examples from your experience
    • Discuss scalability benefits
  3. Best Practices:

    • Mention Angular’s opinionated nature
    • Discuss built-in security features
    • Emphasize testing capabilities
  4. Performance Considerations:

    • Talk about change detection strategies
    • Mention lazy loading capabilities
    • Discuss optimization techniques

Test Your Knowledge

Take a quick quiz to test your understanding of this topic.

Test Your Angular Knowledge

Ready to put your skills to the test? Take our interactive Angular quiz and get instant feedback on your answers.