首页 > 解决方案 > Angular @Input 装饰器和其他问题

问题描述

我正在按照 Google Codelabs 上的教程制作 Kanban-fire 应用程序。这是我面临问题的部分的链接。https://developers.google.com/codelabs/building-a-web-app-with-angular-and-firebase#10

我正在使用 Angular CLI 11.0.7、Node 12.18.2、Ubuntu 20.10 64 位、TypeScript 4.1.2。

正如本教程中所解释的,我跟随并进行了所有必要的更改。这是我面临的问题。

起初,我收到了这个错误

属性“任务”没有初始化程序,也没有在构造函数中明确分配。 19 任务:任务;

这是我对应的代码

@Input() task: Task;

它使用以下任务接口

export interface Task {
  id?: string;
  title: string;
  description: string;
}

我尝试通过将@Input 中的任务属性初始化为

@Input() task: Task = {title: 'def title', description: 'def desc'};

在出现这些错误之前一切都很好。

正如您将能够在我分享的链接中看到的那样,我们必须对文件app.component.html中的一些方法以及一些方法进行更改app.component.ts。我进行了更改,现在我收到了这些错误。

Error: src/app/app.component.html:21:34 - error TS2345: Argument of type 'CdkDragDrop<{ id: string; }[] | null, any>' is not assignable to parameter of type 'CdkDragDrop<Task[], Task[]>'.
  Type '{ id: string; }[] | null' is not assignable to type 'Task[]'.
    Type 'null' is not assignable to type 'Task[]'.

21       (cdkDropListDropped)="drop($event)"

Error occurs in the template of component AppComponent.
src/app/app.component.html:27:17 - error TS2739: Type '{ id: string; }' is missing the following properties from type 'Task': title, description

27         cdkDrag [task]="task"></app-task>

为了完整的参考,我在这里app.component.html提供app.component.ts代码

<mat-toolbar color="primary">
  <mat-icon>local_fire_department</mat-icon>
  <span>Kanban Fire</span>
</mat-toolbar>

<div class="content-wrapper">
  <button (click)="newTask()" mat-button>
    <mat-icon>add</mat-icon> Add Task
  </button>
</div>

<div class="container-wrapper">
  <div class="container">
    <h2>Backlog</h2>
    <mat-card
      cdkDropList
      id="todo"
      #todoList="cdkDropList"
      [cdkDropListData]="todo | async"
      [cdkDropListConnectedTo]="[doneList, inProgressList]"
      (cdkDropListDropped)="drop($event)"
      class="list">
      <p class="empty-label" *ngIf="(todo | async)?.length === 0">Empty List</p>
      <app-task
        (edit)="editTask('todo', $event)"
        *ngFor="let task of todo | async"
        cdkDrag [task]="task"></app-task>
    </mat-card>
  </div>

  <div class="container">
    <h2>In Progress</h2>
    <mat-card
      cdkDropList
      id="inProgress"
      #inProgressList="cdkDropList"
      [cdkDropListData]="inProgress | async"
      [cdkDropListConnectedTo]="[todoList, doneList]"
      (cdkDropListDropped)="drop($event)"
      class="list">
      <p class="empty-label" *ngIf="(inProgress | async)?.length === 0">Empty List</p>
      <app-task
        (edit)="editTask('inProgress', $event)"
        *ngFor="let task of inProgress | async"
        cdkDrag [task]="task"></app-task>
    </mat-card>
  </div>

  <div class="container">
    <h2>Done</h2>
    <mat-card
      cdkDropList
      id="done"
      #doneList="cdkDropList"
      [cdkDropListData]="done | async"
      [cdkDropListConnectedTo]="[todoList, inProgressList]"
      (cdkDropListDropped)="drop($event)"
      class="list">
      <p class="empty-label" *ngIf="(done | async)?.length === 0">Empty List</p>
      <app-task
        (edit)="editTask('done', $event)"
        *ngFor="let task of done | async"
        cdkDrag [task]=""></app-task>
    </mat-card>
  </div>
</div>

app.component.ts

import { Component } from '@angular/core';
import { Task } from '../app/task/task';
import { CdkDragDrop, transferArrayItem } from '@angular/cdk/drag-drop';
import { MatDialog } from '@angular/material/dialog';
import { TaskDialogComponent } from '../app/task-dialog/task-dialog.component';
import { TaskDialogResult } from '../app/task-dialog/task-dialog.component';
import { AngularFirestore } from '@angular/fire/firestore';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  todo = this.store.collection('todo').valueChanges({ idField: 'id' });
  inProgress = this.store.collection('inProgress').valueChanges({ idField: 'id' });
  done = this.store.collection('done').valueChanges({ idField: 'id' });

  constructor(private dialog: MatDialog, private store: AngularFirestore) {}

  editTask(list: 'done' | 'todo' | 'inProgress', task: Task): void {
    const dialogRef = this.dialog.open(TaskDialogComponent, {
      width: '270px',
      data: {
        task,
        enableDelete: true,
      }
    });
    dialogRef.afterClosed().subscribe((result: TaskDialogResult) => {
      if (result.delete) {
        this.store.collection(list).doc(task.id).delete();
      } else {
        this.store.collection(list).doc(task.id).update(task);
      }
    });
  }

  drop(event: CdkDragDrop<Task[]>): void {
    if (event.previousContainer === event.container) {
      return;
    }
    const item = event.previousContainer.data[event.previousIndex];
    this.store.firestore.runTransaction(() => {
      const promise = Promise.all([
        this.store.collection(event.previousContainer.id).doc(item.id).delete(),
        this.store.collection(event.container.id).add(item),
      ]);
      return promise;
    });
    transferArrayItem(
      event.previousContainer.data,
      event.container.data,
      event.previousIndex,
      event.currentIndex
    );
  }  
  
  newTask(): void {
    const dialogRef = this.dialog.open(TaskDialogComponent, {
      width: '270px',
      data: {
        task: {}
      }
    });
    dialogRef.afterClosed().subscribe((result: TaskDialogResult) => {
      this.store.collection('todo').add(result.task)
    });
  }
}

任何帮助将不胜感激。

标签: angulartypescriptfirebase

解决方案


感谢@Eliseo 指出这一点。开启严格模式导致这一切发生。

只需在文件中设置strictstrictTemplates标记为 false 。tsconfig.json


推荐阅读