OpenClaw
Deploy a managed OpenClaw agent in 60 seconds
Launch on Hostinger →
Hermes Agent
Run your Hermes agent, fully managed
Launch on Hostinger →
Apify
6,000+ web scrapers for your agent, free to start
Try Apify free →
Firecrawl
Crawl and scrape any site into clean data
Try Firecrawl free →
Context.dev
One API to scrape, enrich, and extract the web
Start building free →
SetupClaw
Done-for-you OpenClaw for founders and teams
Get it set up for you →
DataForSEO
SEO data APIs for your agent, $1 free credit
Try DataForSEO free →
Your product here
Reach thousands of AI builders a month
Learn more →
Claude Market
Menu
SkillsMCPPluginsSubmit MCPSkillPluginMCPMCP, plugin, or skillAdvertise
Claude Market
SkillsMCPPluginsSubmit MCPSkillPluginMCPMCP, plugin, or skillAdvertise
Skills/analogjs/angular-skills/angular-di
angular-di logo

angular-di

analogjs/angular-skills
5K installs594 stars
Run it on Hostinger →Free API →|View on GitHub

Installation

npx skills add https://github.com/analogjs/angular-skills --skill angular-di

Summary

Implement dependency injection in Angular v20+ using inject(), injection tokens, and provider configuration. Use for service architecture, providing dependencies at different levels, creating injectable tokens, and managing singleton vs scoped services. Triggers on service creation, configuring providers, using injection tokens, or understanding DI hierarchy.

SKILL.md

Angular Dependency Injection

Configure and use dependency injection in Angular v20+ with inject() and providers.

Basic Injection

Using inject()

Prefer inject() over constructor injection:

import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { User } from './user.service';

@Component({
  selector: 'app-user-list',
  template: `...`,
})
export class UserList {
  // Inject dependencies
  private http = inject(HttpClient);
  private userService = inject(User);
  
  // Can use immediately
  users = this.userService.getUsers();
}

Injectable Services

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

@Injectable({
  providedIn: 'root', // Singleton at root level
})
export class User {
  private http = inject(HttpClient);
  
  private users = signal<User[]>([]);
  readonly users$ = this.users.asReadonly();
  
  async loadUsers() {
    const users = await firstValueFrom(
      this.http.get<User[]>('/api/users')
    );
    this.users.set(users);
  }
}

Provider Scopes

Root Level (Singleton)

// Recommended: providedIn
@Injectable({
  providedIn: 'root',
})
export class Auth {}

// Alternative: in app.config.ts
export const appConfig: ApplicationConfig = {
  providers: [
    Auth,
  ],
};

Component Level (Instance per Component)

@Component({
  selector: 'app-editor',
  providers: [EditorState], // New instance for each component
  template: `...`,
})
export class Editor {
  private editorState = inject(EditorState);
}

Route Level

export const routes: Routes = [
  {
    path: 'admin',
    providers: [Admin], // Shared within this route tree
    children: [
      { path: '', component: AdminDashboard },
      { path: 'users', component: AdminUsers },
    ],
  },
];

Injection Tokens

Creating Tokens

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

// Simple value token
export const API_URL = new InjectionToken<string>('API_URL');

// Object token
export interface AppConfig {
  apiUrl: string;
  features: {
    darkMode: boolean;
    analytics: boolean;
  };
}

export const APP_CONFIG = new InjectionToken<AppConfig>('APP_CONFIG');

// Token with factory (self-providing)
export const WINDOW = new InjectionToken<Window>('Window', {
  providedIn: 'root',
  factory: () => window,
});

export const LOCAL_STORAGE = new InjectionToken<Storage>('LocalStorage', {
  providedIn: 'root',
  factory: () => localStorage,
});

Providing Token Values

// app.config.ts
export const appConfig: ApplicationConfig = {
  providers: [
    { provide: API_URL, useValue: 'https://api.example.com' },
    {
      provide: APP_CONFIG,
      useValue: {
        apiUrl: 'https://api.example.com',
        features: { darkMode: true, analytics: true },
      },
    },
  ],
};

Injecting Tokens

@Injectable({ providedIn: 'root' })
export class Api {
  private apiUrl = inject(API_URL);
  private config = inject(APP_CONFIG);
  private window = inject(WINDOW);
  
  getBaseUrl(): string {
    return this.apiUrl;
  }
}

Provider Types

useClass

// Provide implementation
{ provide: Logger, useClass: ConsoleLogger }

// Conditional implementation
{
  provide: Logger,
  useClass: environment.production
    ? ProductionLogger
    : ConsoleLogger,
}

useValue

// Static values
{ provide: API_URL, useValue: 'https://api.example.com' }

// Configuration objects
{ provide: APP_CONFIG, useValue: { theme: 'dark', language: 'en' } }

useFactory

// Factory with dependencies
{
  provide: User,
  useFactory: (http: HttpClient, config: AppConfig) => {
    return new User(http, config.apiUrl);
  },
  deps: [HttpClient, APP_CONFIG],
}

// Async factory (not recommended - use provideAppInitializer)
{
  provide: CONFIG,
  useFactory: () => fetch('/config.json').then(r => r.json()),
}

useExisting

// Alias to existing provider
{ provide: AbstractLogger, useExisting: ConsoleLogger }

// Multiple tokens pointing to same instance
providers: [
  ConsoleLogger,
  { provide: Logger, useExisting: ConsoleLogger },
  { provide: ErrorLogger, useExisting: ConsoleLogger },
]

Injection Options

Optional Injection

@Component({...})
export class My {
  // Returns null if not provided
  private analytics = inject(Analytics, { optional: true });
  
  trackEvent(name: string) {
    this.analytics?.track(name);
  }
}

Self, SkipSelf, Host

@Component({
  providers: [Local],
})
export class Parent {
  // Only look in this component's injector
  private local = inject(Local, { self: true });
}

@Component({...})
export class Child {
  // Skip this component, look in parent
  private parentService = inject(ParentSvc, { skipSelf: true });

  // Only look up to host component
  private hostService = inject(Host, { host: true });
}

Multi Providers

Collect multiple values for same token:

// Token for multiple validators
export const VALIDATORS = new InjectionToken<Validator[]>('Validators');

// Provide multiple values
providers: [
  { provide: VALIDATORS, useClass: RequiredValidator, multi: true },
  { provide: VALIDATORS, useClass: EmailValidator, multi: true },
  { provide: VALIDATORS, useClass: MinLengthValidator, multi: true },
]

// Inject as array
@Injectable()
export class Validation {
  private validators = inject(VALIDATORS); // Validator[]
  
  validate(value: string): ValidationError[] {
    return this.validators
      .map(v => v.validate(value))
      .filter(Boolean);
  }
}

HTTP Interceptors (Multi Provider)

// Interceptors use multi providers internally
export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(
      withInterceptors([
        authInterceptor,
        loggingInterceptor,
        errorInterceptor,
      ])
    ),
  ],
};

App Initializers

Run async code before app starts using provideAppInitializer:

import { provideAppInitializer, inject } from '@angular/core';

export const appConfig: ApplicationConfig = {
  providers: [
    Config,
    provideAppInitializer(() => {
      const configService = inject(Config);
      return configService.loadConfig();
    }),
  ],
};

Multiple Initializers

providers: [
  provideAppInitializer(() => {
    const config = inject(Config);
    return config.load();
  }),
  provideAppInitializer(() => {
    const auth = inject(Auth);
    return auth.checkSession();
  }),
]

Environment Injector

Create injectors programmatically:

import { createEnvironmentInjector, EnvironmentInjector, inject } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class Plugin {
  private parentInjector = inject(EnvironmentInjector);
  
  loadPlugin(providers: Provider[]): EnvironmentInjector {
    return createEnvironmentInjector(providers, this.parentInjector);
  }
}

runInInjectionContext

Run code with injection context:

import { runInInjectionContext, EnvironmentInjector, inject } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class Utility {
  private injector = inject(EnvironmentInjector);
  
  executeWithDI<T>(fn: () => T): T {
    return runInInjectionContext(this.injector, fn);
  }
}

// Usage
utilityService.executeWithDI(() => {
  const http = inject(HttpClient);
  // Use http...
});

For advanced patterns, see references/di-patterns.md.

Score

0–100
69/ 100

Grade

C

Popularity21/30

4,766 installs — solid traction.

Completeness27/30

Documented: full SKILL.md body, description, one-line install. Missing: category/license metadata.

Trust15/25

Community skill with a public GitHub source repository you can review.

Freshness6/15

No update timestamp is tracked for this skill in our catalog.

Scored automatically from popularity, completeness, trust, and freshness — computed only from data in our catalog, never fabricated.

Proud of your score? Add this badge to your README.

Paste a snippet into your GitHub README. The badge updates automatically and links back to this page.

Angular Di skill score badge previewScore badge

Markdown

[![Angular Di skill](https://www.claudemarket.ai/skills/analogjs/angular-skills/angular-di/badges/score.svg)](https://www.claudemarket.ai/skills/analogjs/angular-skills/angular-di)

HTML

<a href="https://www.claudemarket.ai/skills/analogjs/angular-skills/angular-di"><img src="https://www.claudemarket.ai/skills/analogjs/angular-skills/angular-di/badges/score.svg" alt="Angular Di skill"/></a>

Angular Di FAQ

How do I install the Angular Di skill?

Run “npx skills add https://github.com/analogjs/angular-skills --skill angular-di” in your terminal. The skill is added to your agent's skills directory and picked up automatically on the next run — no restart or extra configuration needed.

What does the Angular Di skill do?

Implement dependency injection in Angular v20+ using inject(), injection tokens, and provider configuration. Use for service architecture, providing dependencies at different levels, creating injectable tokens, and managing singleton vs scoped services. Triggers on service creation, configuring providers, using injection tokens, or understanding DI hierarchy. The full SKILL.md on this page shows the exact instructions the skill gives your agent.

Is the Angular Di skill free?

Yes. Angular Di is a free, open-source skill published from analogjs/angular-skills. As with any third-party skill, review the source repository before installing it into an agent with sensitive access.

Does Angular Di work with Claude Code and OpenClaw?

Yes. Skills use the portable SKILL.md format, so Angular Di works with Claude Code, OpenClaw, Codex, Hermes, and any other agent that reads SKILL.md skills.

Recommended skills

Browse all →
find-skills logo

find-skills

vercel-labs/skills

2.8M installsInstall
grill-me logo

grill-me

mattpocock/skills

745K installsInstall
frontend-design logo

frontend-design

anthropics/skills

738K installsInstall
grill-with-docs logo

grill-with-docs

mattpocock/skills

632K installsInstall
agent-browser logo

agent-browser

vercel-labs/agent-browser

622K installsInstall
improve-codebase-architecture logo

improve-codebase-architecture

mattpocock/skills

608K installsInstall

Related guides

Hand-picked reading to help you choose, install, and use agent skills.

GuideBest Openclaw Skills 2026GuideHow To Evaluate Openclaw Skill Before InstallingGuideOpenclaw Skills Complete Guide

Skills by category

FrontendBackend & APIsTesting & QASecurityDevOps & CI/CDMCP & ToolingAutomationData & Analysis+20 more

MCP servers by category

AI & MLDeveloper ToolsVector & MemoryFiles & DocsDatabasesFinance & PaymentsBrowser & ScrapingCommunication+8 more

Plugins by category

developmentproductivitycommunicationdesignsecuritydatabaseworkflowcompliance+34 more

The Agent Stack

Weekly Claude Code, Agent SDK, and MCP moves worth your time — free.

Claude Market

AI agent skills directory, marketplace, and workflow hub for OpenClaw, Hermes Agent, Claude Code, Codex, and MCP-powered operator stacks.

Independent project, not affiliated with Anthropic.

Resources

  • Browse Skills
  • Browse MCP Servers
  • Browse Plugins

More

  • Submit a Tool
  • Create a Skill
  • Advertise
  • Free Tools
  • API
  • Shipping
  • Contact
  • Terms
  • Privacy
© 2026 Claude Market · Not affiliated with Anthropic
Fazier badgeFeatured on Twelve ToolsFeatured on Wired BusinessRemote OpenClaw - Featured on AI Agents DirectoryListed on Turbo0Featured on Uneed