You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 13出现NullInjectorError:无ModuleSkillCollectionComponent提供者求助

解决Angular 13中NullInjectorError组件依赖问题

在Angular 13中生成新组件后出现如下错误,删除该组件后错误仍触发:

Uncaught (in promise): NullInjectorError:
R3InjectorError(AppModule)[HttpService ->
ModuleSkillCollectionComponent -> ModuleSkillCollectionComponent ->
ModuleSkillCollectionComponent]: NullInjectorError: No provider for
ModuleSkillCollectionComponent!

控制台提示指向导航组件代码:

<nav class="navbar max-w-full w-full mx-auto">
  <div class="flex-1">
    <div class="w-full top-0 border-b">
      <ul class="menu menu-horizontal w-screen">
        <li class="left-0 top-0 font-bold"><a href="">CompetentieApp</a></li>
        <li class="mr-10">
          <a routerLinkActive="tab-active" href="/faq">Eindniveaus</a>
        </li>
        <li class="mr-10"><a href="/faq">Overzicht Alle Modules</a></li>
        <li class="mr-10"><a href="/faq">Beheer</a></li>
        <li class="mr-10">
          <a routerLinkActive="tab-active" routerLink="moduleCompetenties">Logout</a>
        </li>
        <img
          class="absolute w-14 md:w-36 mr-10 right-0 top-0"
          src="assets/logo.png"
          alt="logo"
        />
      </ul>
    </div>
  </div>
</nav>
<router-outlet></router-outlet>

相关配置与代码文件

1. app-routing.ts

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'moduleCompetenties', component: ModuleSkillCollectionComponent },
  { path: '**', redirectTo: 'home', pathMatch: 'full' },
];

@NgModule({
  imports: [
      CommonModule,
      RouterModule.forRoot(routes)
  ],
  exports: [RouterModule],
})
export class AppRoutingModule {}

2. http.service.ts

@Injectable({ providedIn: 'root' })
export class HttpService {


  // moduleSkillJson: ModuleSkillJSON[] = [];
  // private isGetting = false;

  constructor(private http: HttpClient, private moduleSKillClass: ModuleSkillCollectionComponent) {}

  post() {
    this.http.post('http://localhost:8080/add', this.postBody).subscribe(() => {
      console.log(this.postBody);
    });
  }

  getSkill(skillJson: Skill[]) {
    this.http.get<{[key: string] : Skill}>(environment.apiUrl + '/skillCollection')
        .pipe(
            map((res) => {
                  // console.log(res);
                  const skillDetailsArray: Skill[] = [];
                  for (const key in res) {
                    if (res.hasOwnProperty(key)) {
                      skillDetailsArray.push({...res[key], id: key})
                    }
                  }
                  // console.log(skillDetailsArray);
                  return skillDetailsArray;
                }
            )
        ).subscribe(skills => {
          // console.log(skills);
          skillJson = skills;
          // console.log("SkillDetails has " + this.skillJson.length + " entries.");
        }
    );
  }

  getModuleSkill(moduleSkillJson: ModuleSkillJSON[]) {
    this.http
        .get<{[key: string] : ModuleSkillJSON}>(environment.apiUrl + "/moduleSkill")
        .pipe(
            map((res) => {
              // console.log(res);
              const moduleSkill: ModuleSkillJSON[] = [];
              for (const key in res) {
                if (res.hasOwnProperty(key)) {
                  moduleSkill.push({...res[key], id: key})
                }
              }
              console.log(moduleSkill);
              return moduleSkill;
            })
        ).subscribe(moduleSkills => {
      moduleSkillJson = moduleSkills;
      this.moduleSKillClass.entriesLooper(moduleSkillJson);
    });
    // console.log("SkillDetails has " + this.moduleSkillJson.length + " entries.");
  }
}

3. App.module.ts

@NgModule({
  declarations: [AppComponent, ModuleSkillCollectionComponent],
  imports: [
    BrowserModule,
    AppRoutingModule,
    ReactiveFormsModule,
    HttpClientModule,
  ],
  providers: [HttpService],
  bootstrap: [AppComponent],
})
export class AppModule {}

4. module-skill-collection.component.ts

export class ModuleSkillCollectionComponent implements OnInit {
  showTable: Boolean = false;
  loop: boolean = true;
  cohort: string = '22-23';
  moduleSkillJson: ModuleSkillJSON[];
  skillJson: Skill[] = [];
  entries: number[] = [];
  i: number = 1;

    constructor(private service: HttpService) {}

  ngOnInit(): void {
      this.getModuleSkills();
      this.getSkill();
  }

  isActive() {
    this.showTable = !this.showTable;
  }

    counter(i: number) {
        return new Array(i);
    }

    getSkill() {
        this.service.getSkill(this.skillJson);
    }

    getModuleSkills() {
        this.service.getModuleSkill(this.moduleSkillJson);
        this.entriesLooper(this.moduleSkillJson);
    }

    entriesLooper(moduleSKills: ModuleSkillJSON[]): number[] {
        for (let modulesSKill of moduleSKills) {
            this.entries.push(modulesSKill.entry);
        }
        return this.entries;
    }

}

export interface Skill {
    id?: string;
    skillGroupName: string;
    skillGroupType: string;
    skillDetailName: string;
    skillDetailType: string;
}

export interface ModuleSkillJSON {
    moduleCode: string;
    moduleName: string;
    skill: Array<Skill>[];
    entry: number;
    exist: number;
    id?: string;
}

解决方案

问题根源

错误核心是**HttpService构造函数中注入了ModuleSkillCollectionComponent组件**。Angular组件不能作为依赖注入到服务中:组件是由Angular在路由加载、模板渲染等场景下创建的实例,并非全局可提供的依赖项,这种组件与服务的循环依赖直接触发了NullInjectorError。

修复步骤

  1. 移除服务中对组件的依赖
    修改http.service.ts的构造函数,删除组件注入:

    constructor(private http: HttpClient) {} // 移除private moduleSKillClass: ModuleSkillCollectionComponent
    
  2. 重构服务方法,返回Observable而非直接处理
    服务只负责数据请求,将数据处理逻辑交回组件,修改getModuleSkill方法:

    getModuleSkill(): Observable<ModuleSkillJSON[]> {
      return this.http
          .get<{[key: string] : ModuleSkillJSON}>(environment.apiUrl + "/moduleSkill")
          .pipe(
              map((res) => {
                const moduleSkill: ModuleSkillJSON[] = [];
                for (const key in res) {
                  if (res.hasOwnProperty(key)) {
                    moduleSkill.push({...res[key], id: key})
                  }
                }
                console.log(moduleSkill);
                return moduleSkill;
              })
          );
    }
    
  3. 调整组件调用逻辑
    在组件中订阅服务返回的Observable,自行处理数据:

    getModuleSkills() {
        this.service.getModuleSkill().subscribe(moduleSkills => {
          this.moduleSkillJson = moduleSkills;
          this.entriesLooper(this.moduleSkillJson);
        });
    }
    
  4. 修复getSkill方法的传值问题
    原方法中直接赋值skillJson = skills无法修改组件变量,同样改为返回Observable:

    // 服务中修改getSkill
    getSkill(): Observable<Skill[]> {
      return this.http.get<{[key: string] : Skill}>(environment.apiUrl + '/skillCollection')
          .pipe(
              map((res) => {
                    const skillDetailsArray: Skill[] = [];
                    for (const key in res) {
                      if (res.hasOwnProperty(key)) {
                        skillDetailsArray.push({...res[key], id: key})
                      }
                    }
                    return skillDetailsArray;
                  }
              )
          );
    }
    
    // 组件中修改调用
    getSkill() {
        this.service.getSkill().subscribe(skills => {
          this.skillJson = skills;
        });
    }
    
  5. 确认配置正确性
    确保AppModule的providers数组中没有添加组件(当前代码已符合要求)。

内容的提问来源于stack exchange,提问作者H. Motsu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 09:15:42