简体   繁体   English

Angular @Input 装饰器等问题

[英]Angular @Input decorator and other issues

I am making the Kanban-fire app by following the tutorial on Google Codelabs.我正在按照 Google Codelabs 上的教程制作 Kanban-fire 应用程序。 This is the link of the part where I'm facing issues.这是我面临问题的部分的链接。 https://developers.google.com/codelabs/building-a-web-app-with-angular-and-firebase#10 https://developers.google.com/codelabs/building-a-web-app-with-angular-and-firebase#10

I'm using Angular CLI 11.0.7, Node 12.18.2, Ubuntu 20.10 64bit, TypeScript 4.1.2.我正在使用 Angular CLI 11.0.7、节点 12.18.2、Ubuntu 20.10 64 位、Z558B544CF685F39D38B67E4903E39C.3

As explained in the tutorial, I followed along and made all the necessary changes.正如本教程中所解释的,我跟随并进行了所有必要的更改。 Here's the issue that I'm facing.这是我面临的问题。

At first, I was getting this error起初,我收到了这个错误

Property 'task' has no initializer and is not definitely assigned in the constructor.属性“任务”没有初始化程序,也没有在构造函数中明确分配。 19 task: Task; 19 任务:任务;

and this is my corresponding code这是我对应的代码

@Input() task: Task;

It uses the following Task interface它使用以下任务接口

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

I tried to solve this error by initializing the task property in @Input as我尝试通过将@Input 中的任务属性初始化为

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

and it was all good until these errors arose.在出现这些错误之前一切都很好。

As you'll be able to see in the link that I've shared, that we have to make changes to app.component.html as well as some methods in app.component.ts file.正如您在我分享的链接中看到的那样,我们必须对app.component.html以及app.component.ts文件中的一些方法进行更改。 I made the changes and now I'm getting these errors.我进行了更改,现在我收到了这些错误。

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)"

and

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>

For complete reference, I am providing app.component.html as well as app.component.ts code here为了完整的参考,我在这里提供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 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)
    });
  }
}

Any help will be appreciated.任何帮助将不胜感激。

Thanks to @Eliseo for pointing this out.感谢@Eliseo 指出这一点。 The strict mode being turned on caused all this to happen.开启严格模式导致这一切发生。

Just set strict and strictTemplates flags to false in tsconfig.json file.只需在tsconfig.json文件中将strictstrictTemplates标志设置为 false。

I had a similar problem in an application I was working on.我正在处理的应用程序中遇到了类似的问题。 I eventually paid close attention to my error message similar to yours... your error message was --> "Property 'task' has no initializer and is not definitely assigned in the constructor. 19 task: Task;我最终密切注意与您类似的错误消息...您的错误消息是-->“属性'任务'没有初始化程序,并且未在构造函数中明确分配。19 任务:任务;

In my case my error was -->"Property 'election' has no initializer and is not definitely assigned in the constructor.ts(2564)"在我的情况下,我的错误是 -->"Property 'election' has no initializer 并且没有在 constructor.ts(2564) 中明确分配"

my input statement was我的输入语句是

@Input() election: Election

and I added this line in my constructor which was formerly not populated with this initialization.我在我的构造函数中添加了这一行,该构造函数以前没有填充这个初始化。

 this.election =ELECTIONS[0]

this solved my problem这解决了我的问题

I guess you have to initialize in the constructor whatever it is you are trying to import.我想您必须在构造函数中进行初始化,无论您要导入什么。

In summary source Component -->总结源组件-->

elections-main-list.component.html

    <app-election-item
    
    *ngFor="let election of elections"
    
    [election]="election" >
    </app-election-item>

Import component导入组件

election-item-component.ts
export  class ElectionItemComponent implements OnInit{
 
  @Input() election: Election
 
  constructor() {
    this.election =ELECTIONS[0]
    
   }


As I  have only been using Angular for a short period of time the lesson I learned was to pay close attention to the error message. anyway this solution worked perfectly and on the next step.... 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM