Interview answer drill

Use this Angular interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.

What responsibilities belong inside an Angular component vs a service?Frontend interview answer

HighIntermediateAngular
Interview focus

This Angular interview question tests whether you can explain Angular component vs service: what belongs where, connect it to production trade-offs, and handle common follow-up questions.

  • Angular component vs service: what belongs where explanation without falling back to memorized docs wording
  • Components and Services reasoning, edge cases, and production failure modes
  • How you would answer the most likely Angular interview follow-up
Practice more Angular interview questions
Interview quick answer

Angular components should focus on UI/presentation and user interactions, while services should hold reusable logic, business rules, and side effects (HTTP, caching, state). Clean separation keeps components thin, improves testability, and avoids duplicated logic across the app.

Full interview answer

Overview

Use components for rendering + wiring UI events to actions. Use services for reusable logic and side effects (HTTP, caching, state, orchestration). A good component reads like a “view model composer”, not a mini back-end.

Area

Component (belongs here)

Service (belongs here)

UI rendering

Template bindings, UI composition, structural directives, view-only formatting

No DOM/template concerns

User interaction

Click handlers, form submit handlers, mapping UI events → intent/actions

Input validation rules that are reusable across screens

State

Ephemeral UI state (open/closed, selected tab, local filters, loading flags for UI)

Shared/stateful app logic (cache, session data, cross-component state), facades

Business rules

Minimal (only what’s needed to connect UI to rules)

Core rules (pricing logic, permission checks, normalization, mapping DTO→domain)

Data access

Never call low-level APIs directly (avoid HttpClient usage in components)

HTTP calls, retries, error mapping, caching, request dedupe

Reusability

Rare (components can be reusable, but should avoid app-specific business logic)

High (same service can be used by multiple components)

Testing

Shallow: assert template bindings + event wiring + observable usage

Deep: unit test rules/side effects without rendering

Component vs Service responsibilities

Rule of thumb

If the code depends on how something is shown (DOM, template state, view events) → component. If it depends on what something means (rules, data fetching, caching, orchestration) → service.

Worked example: duplicated business rule across two screens

If both a checkout page and an admin refund page need the same “can this order be refunded?” rule, that logic does not belong in either component. Each component should ask a service/facade for the answer and stay focused on rendering the result.

TYPESCRIPT
// ❌ Fat component: rule duplicated in multiple screens
export class OrdersPageComponent {
  canRefund(order: Order): boolean {
    return order.status === 'paid' && !order.locked && order.total > 0;
  }
}

// ✅ Move the reusable rule behind a service boundary
@Injectable({ providedIn: 'root' })
export class OrdersPolicyService {
  canRefund(order: Order): boolean {
    return order.status === 'paid' && !order.locked && order.total > 0;
  }
}

export class OrdersPageComponent {
  constructor(private ordersPolicy: OrdersPolicyService) {}
}
                  
TYPESCRIPT
// user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, shareReplay } from 'rxjs';

export interface UserDto { id: string; name: string; }
export interface User { id: string; displayName: string; }

@Injectable({ providedIn: 'root' })
export class UserService {
  private users$?: Observable<User[]>;

  constructor(private http: HttpClient) {}

  getUsers(): Observable<User[]> {
    // Cache + dedupe requests for this session
    this.users$ ??= this.http.get<UserDto[]>('/api/users').pipe(
      // Business mapping belongs here (or a dedicated mapper)
      // so multiple components get consistent data.
      // Keep mapping pure.
      // DTO -> domain model:
      // (If mapping grows, extract to a pure function.)
      shareReplay({ bufferSize: 1, refCount: true })
    ) as unknown as Observable<User[]>;

    return this.users$;
  }
}
                  
TYPESCRIPT
// user-list.component.ts
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Observable, map, startWith } from 'rxjs';
import { UserService, User } from './user.service';

@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserListComponent {
  // UI state belongs here
  readonly search = '';

  // Data stream comes from a service
  readonly users$: Observable<User[]> = this.userService.getUsers();

  // UI-only derived state can be computed in the component
  // (keep it cheap; heavy transforms should be in a service/facade)
  readonly viewModel$ = this.users$.pipe(
    map(users => ({
      users,
      total: users.length
    })),
    startWith({ users: [], total: 0 })
  );

  constructor(private userService: UserService) {}

  onRefreshClick(): void {
    // UI intent: trigger refresh.
    // If refresh needs side-effects (invalidate cache), expose that from the service.
    // e.g. this.userService.invalidateUsersCache();
  }
}
                  

Common mistake

Why it hurts

Fix

HttpClient calls inside components

Duplicates logic, makes components hard to test and reuse

Move data access to a service/facade

Business rules in templates (complex expressions)

Hard to read, hard to test, runs every CD cycle

Compute in TS (component for UI-only, service for reusable rules)

Services manipulating the DOM

Breaks separation, complicates SSR/testing

Keep DOM work in components/directives; services stay UI-agnostic

“God component” that owns everything

Becomes unmaintainable; PRs become risky

Extract services + presentational components; keep the container thin

Typical boundary violations

Extra nuance: service scope

Most services are singletons (providedIn: 'root'). If you need per-component instance state (e.g., a wizard session), provide the service at the component level via providers: [WizardStateService] so each component instance gets its own copy.

Summary

Keep components focused on UI + event wiring + lightweight view-model shaping. Put reusable logic, side effects, data access, and business rules into services (or facades). This separation improves testability, reuse, and long-term maintainability.

Similar questions
Guides
Preparing for interviews?

Use this as one explanation rep, then continue with the Angular interview questions cluster or a guided prep path.