Skip to content
Back to skills

Angular Service Di

ASecurity

> Design Angular services with the right provider scope, injection tokens, and hierarchical injector strategy

  • 20 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 11, 2026
developmenttypescriptangulartestingapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 11, 2026

npx -y skills add Intense-Visions/harness-engineering --skill angular-service-di --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Angular Service Di?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Angular Service Di
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/intense-visions-angular-service-di/badge)](https://www.skillsdirectory.com/skills/intense-visions-angular-service-di)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Angular Service & Dependency Injection

> Design Angular services with the right provider scope, injection tokens, and hierarchical injector strategy

## When to Use

- Creating a shared service (data fetching, state, utilities) and deciding on its scope
- Replacing a module-level provider with `providedIn: 'root'` or a standalone provider
- Using `InjectionToken` to inject non-class values (config objects, feature flags, URLs)
- Injecting services into other services without circular dependencies
- Providing mock implementations in tests

## Instructions

1. Decorate every service with `@Injectable`. Use `providedIn: 'root'` as the default — it makes the service a singleton and tree-shakeable without needing to list it in a module.
2. Use `providedIn: 'root'` for app-wide singletons. Use component-level `providers: [MyService]` only when you need a fresh instance per component subtree.
3. Create `InjectionToken<T>` for any non-class dependency: API base URLs, feature flags, environment config, or factory functions.
4. Use the `inject()` function (Angular 14+) instead of constructor injection when writing standalone functions, guards, or effects. It reads more cleanly and is required outside class constructors.
5. Avoid circular dependencies by extracting shared state into a lower-level service that neither service imports.
6. Prefer `DestroyRef` injection over implementing `OnDestroy` in services — it keeps cleanup co-located with subscription setup.

```typescript
// environment config token
export const API_BASE_URL = new InjectionToken<string>('API_BASE_URL', {
  providedIn: 'root',
  factory: () => 'https://api.example.com',
});

@Injectable({ providedIn: 'root' })
export class ProductService {
  private readonly http = inject(HttpClient);
  private readonly baseUrl = inject(API_BASE_URL);
  private readonly destroyRef = inject(DestroyRef);

  getProducts(): Observable<Product[]> {
    return this.http.get<Product[]>(`${this.baseUrl}/products`);
  }
}

// Override in tests or feature modules
providers: [{ provide: API_BASE_URL, useValue: 'https://staging.example.com' }];
```

```typescript
// Component-scoped service — new instance per component tree
@Component({
  selector: 'app-wizard',
  providers: [WizardStateService], // fresh instance, destroyed with component
  template: `...`,
})
export class WizardComponent {}
```

## Details

**Injector hierarchy:** Angular maintains a tree of injectors that mirrors the component tree. When a token is requested, Angular walks up the tree until it finds a provider. Root injector covers the entire app. Module injectors cover lazy-loaded modules. Component injectors cover a component and its descendants. This hierarchy is the mechanism behind scoped singletons.

**`providedIn: 'root'` vs module providers:** Module providers were the Angular 2–12 idiom. They work but require importing the module to get the service. `providedIn: 'root'` eliminates that coupling and enables tree-shaking — unused services are removed from the bundle automatically.

**`inject()` function:** Available in any injection context (constructor, field initializer, factory function, guard, resolver). It cannot be called in a method body called outside the injection context. Use it freely in class field initializers and `@Component` function callbacks.

**Multi-providers:** Use `multi: true` with a token to collect multiple implementations under one token. Angular's `HTTP_INTERCEPTORS` and `APP_INITIALIZER` tokens use this pattern.

```typescript
export const VALIDATORS = new InjectionToken<Validator[]>('VALIDATORS');
providers: [
  { provide: VALIDATORS, useClass: EmailValidator, multi: true },
  { provide: VALIDATORS, useClass: PhoneValidator, multi: true },
];
// inject(VALIDATORS) → [EmailValidator, PhoneValidator]
```

**Service isolation for testing:** Provide a mock in `TestBed.configureTestingModule`:

```typescript
TestBed.configureTestingModule({
  providers: [{ provide: ProductService, useValue: mockProductService }],
});
```

**Tree-shakeable tokens:** Pair `InjectionToken` with a `factory` to make the default value tree-shakeable:

```typescript
export const FEATURE_FLAGS = new InjectionToken<FeatureFlags>('FEATURE_FLAGS', {
  providedIn: 'root',
  factory: () => ({ darkMode: false, betaSearch: false }),
});
```

## Source

https://angular.dev/guide/di

## Process

1. Read the instructions and examples in this document.
2. Apply the patterns to your implementation, adapting to your specific context.
3. Verify your implementation against the details and edge cases listed above.

## Harness Integration

- **Type:** knowledge — this skill is a reference document, not a procedural workflow.
- **No tools or state** — consumed as context by other skills and agents.

## Success Criteria

- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.

Files in this skill

  • SKILL.md4.9 KB
  • skill.yaml884 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…