我正在利用 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 在提供程序中。
如有任何帮助,我们将不胜感激。
问题出在 FlashcardComponent 中:
constructor(flashcard: Flashcard) {
this.flashcard = flashcard;
}
您只能在构造函数中注入提供的服务。使用 @Input 时,无需将其添加到构造函数中。
为什么抽认卡 HTML 结尾代码带有
export default FlashcardComponent
?