角度空喷油器错误。 “NullInjectorError:没有[对象]的提供者”

问题描述 投票:0回答:2

我正在利用 Angular、Node.js、Express 和 PostgreSQL 构建一个基本的 CRUD 闪存卡应用程序。我收到错误:

flashcards-area.component.ts:24 ERROR NullInjectorError: R3InjectorError(AppModule)[Flashcard -> Flashcard -> Flashcard]: 
  NullInjectorError: No provider for Flashcard!
    at NullInjector.get (core.mjs:6368:27)
    at R3Injector.get (core.mjs:6795:33)
    at R3Injector.get (core.mjs:6795:33)
    at R3Injector.get (core.mjs:6795:33)
    at ChainedInjector.get (core.mjs:13866:36)
    at lookupTokenUsingModuleInjector (core.mjs:3290:39)
    at getOrCreateInjectable (core.mjs:3335:12)
    at Module.ɵɵdirectiveInject (core.mjs:10881:12)
    at NodeInjectorFactory.FlashcardComponent_Factory [as factory] (flashcard.component.ts:11:32)
    at getNodeInjectable (core.mjs:3520:44)

我构建了一个 Flashcard 类、一个 FlashcardArea 父组件和一个在父组件中显示获取的数据的 Flashcard 组件。

抽认卡类别:

export class Flashcard {
    public id?: any;
    public question:string; 
    public answer: string;
    public learned: boolean = false;
    public chapter?: number;
    public displayed?: boolean = true;

    constructor(question: string, answer: string, chapter?: number, learned?: boolean, id?: any, displayed?: boolean){
        this.question = question;
        this.answer = answer;
        this.chapter = chapter;
        this.id = id;
    }
}

export default Flashcard;

检索 PostgreSQL 数据库的抽认卡列表的服务:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Observable, of, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';
import { Flashcard } from '../classes/flashcard';
import { map } from 'rxjs/operators';
import { Subject } from 'rxjs';

const httpOptions = {
    headers: new HttpHeaders({'Content-Type': 'application/json'})
};

@Injectable({
  providedIn: 'root'
})
export class FullFlashcardsListService {
    
    private baseURL: string = "/api/v1/flashcards";

  constructor(private http: HttpClient) { }


    getAll() {
        return this.http.get<Flashcard[]>(this.baseURL);
    } 
};

export default FullFlashcardsListService;

抽认卡区域组件:

import { Component, OnInit } from '@angular/core';
import { Flashcard } from '../classes/flashcard'
import { FullFlashcardsListService } from '../services/full-flashcards-list.service';

@Component({
  selector: 'app-flashcards-area',
  templateUrl: './flashcards-area.component.html',
  styleUrls: ['./flashcards-area.component.css'],
})
export class FlashcardsAreaComponent implements OnInit {
    
  fullFlashcards?: Flashcard[] = [];

  constructor(
    private fullFlashcardsListService: FullFlashcardsListService,
     ) {}

  ngOnInit(): void {
    this.retrieveFlashcards();
  }

  retrieveFlashcards() {
    this.fullFlashcardsListService.getAll()
        .subscribe(response => {
            console.log(response);
            this.fullFlashcards = response
        })
    }

抽认卡区域 HTML:

<div class="flashcards-container">
    <app-flashcard *ngFor="let card of fullFlashcards; let i = index" [flashcard]="card" (deleteCard)="deleteConfirmation(i)" (refreshFlashcards)="retrieveFlashcards()"></app-flashcard>
</div>

在抽认卡区域显示的抽认卡组件

import { Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core';
import { Flashcard } from '../classes/flashcard';
import FullFlashcardsListService from '../services/full-flashcards-list.service';

@Component({
  selector: 'app-flashcard',
  templateUrl: './flashcard.component.html',
  styleUrls: ['./flashcard.component.css']
})

export class FlashcardComponent implements OnInit {
    @Input() flashcard!: Flashcard;
    showAnswer: boolean = false;
    displayed: boolean = true;
    delete: boolean = false;
    @Output() dontDisplay = new EventEmitter();
    @Output() deleteCard = new EventEmitter();

  constructor(flashcard: Flashcard) {
        this.flashcard = flashcard;
   }

  ngOnInit(): void {
  }

  revealAnswer() {
    this.showAnswer = !this.showAnswer;
  }

  hideCard() {
    this.dontDisplay.emit();
  }

  removeCard() {
    this.deleteCard.emit();
  }
}

抽认卡 HTML

<div class="flashcard-container" *ngIf="flashcard.displayed">
    <mat-card  class="flashcard">
        <mat-card-title-group class="mat-card-title">
            <mat-card-title class="title">Chapter {{flashcard.chapter}}</mat-card-title>
            <button mat-button class="check" (click)="hideCard()">
                <mat-icon class="icon" >check</mat-icon>
            </button>
            <button mat-button class="trash" (click)="removeCard()">
                <mat-icon class="icon">delete</mat-icon>
            </button>
        </mat-card-title-group>
        
        <mat-divider class="material-divider"></mat-divider>
        <div class="answer_container" (click)="revealAnswer()">
            <mat-card-content  class="flashcard_question">
                {{flashcard.question}}
            </mat-card-content>
            <mat-card-content *ngIf="showAnswer" class="flashcard_answer">
                {{flashcard.answer}}
            </mat-card-content>
        </div>
    </mat-card>
</div>
export default FlashcardComponent;

这是我的app.module.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { MatCardModule } from '@angular/material/card';
import { MatInputModule } from '@angular/material/input';
import { MatDividerModule } from '@angular/material/divider';
import { FormsModule } from '@angular/forms';
import {MatSidenavModule} from '@angular/material/sidenav';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NavbarComponent } from './navbar/navbar.component';
import { EntryCardComponent } from './entry-card/entry-card.component';
import { TitleHeadingComponent } from './title-heading/title-heading.component';
import { FlashcardComponent } from './flashcard/flashcard.component';
import { FlashcardsAreaComponent } from './flashcards-area/flashcards-area.component';
import { ResetButtonComponent } from './reset-button/reset-button.component';
import { FlashcardsListService } from './services/flashcards-list.service';
import { HttpClientModule } from '@angular/common/http';
import { TrashButtonComponent } from './trash-button/trash-button.component';
import { FullFlashcardsListService } from './services/full-flashcards-list.service';
import { CurrentDisplayedFlashcardsService } from './services/current-displayed-flashcards.service';

@NgModule({
  declarations: [
    AppComponent,
    NavbarComponent,
    EntryCardComponent,
    TitleHeadingComponent,
    FlashcardComponent,
    FlashcardsAreaComponent,
    ResetButtonComponent,
    TrashButtonComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    MatToolbarModule,
    MatButtonModule,
    MatIconModule,
    MatMenuModule,
    MatCardModule,
    MatInputModule,
    MatDividerModule,
    FormsModule,
    MatSidenavModule,
    HttpClientModule,
  ],
  providers: [
    FlashcardsListService,
    FullFlashcardsListService,
    CurrentDisplayedFlashcardsService
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

该服务被标记为可注入,HTTPClientModule 在我的导入中,FullFlashcardsListService 在提供程序中。

如有任何帮助,我们将不胜感激。

angular typescript service
2个回答
0
投票

问题出在 FlashcardComponent 中:

constructor(flashcard: Flashcard) {
   this.flashcard = flashcard;
}

您只能在构造函数中注入提供的服务。使用 @Input 时,无需将其添加到构造函数中。


0
投票

为什么抽认卡 HTML 结尾代码带有

export default FlashcardComponent

© www.soinside.com 2019 - 2024. All rights reserved.