javascript @Input()为未定义,即使@Input()数据在屏幕上可见

js4nwp54  于 2023-03-16  发布在  Java
关注(0)|答案(3)|浏览(180)

我有一个用Angular 12制作的大型应用程序,其中一个部分有一个父组件和一个子组件。
父组件(HTML):

<app-sidenav></app-sidenav>
<div class="row fadeIn animated">
  <div class="col s12  m-0 p-2 pt-5">
    <span class="card-title col s6 pt-4" style="font-size: x-large;">
      {{'Tasks' | translate}}
    </span>

    <div class="col s6">
      <app-filter [tasks]="tasks"></app-filter>
    </div>
  </div>
  <div class="col s12">
    <mat-tab-group dynamicHeight mat-align-tabs="center" class="p-2 pb-0" (selectedIndexChange)="setTab($event)"
    [selectedIndex]="selectedTab" #tabGroup>
      <mat-tab *ngIf="!searching" matBadge="7">
        <ng-template mat-tab-label>
          <div class="mr-5 ml-5 pr-5 pl-5">
            {{'Open' | translate}}
          </div>
          <span *ngIf="openTasks.length > 0" class="btn btn-small btn-floating blue lighten-3 pulse">
            {{openTasks.length}}
          </span>
        </ng-template>
        <div class="card m-1">
          <app-queue-table [dataSourceInput]="openTasks"></app-queue-table>
        </div>
      </mat-tab>
      <mat-tab *ngIf="!searching">
        <ng-template mat-tab-label>
          <div class="mr-5 ml-5 pr-5 pl-5">
            {{'In Progress' | translate}}
          </div>
          <span *ngIf="inProgressTasks.length > 0" class="btn btn-small btn-floating weg-blue darken-4"> {{inProgressTasks.length}}
          </span>
        </ng-template>
        <div class="card m-1">
          <app-queue-table [dataSourceInput]="inProgressTasks"></app-queue-table>
        </div>
      </mat-tab>
      <mat-tab *ngIf="!searching">
        <ng-template mat-tab-label>
          <div class="mr-5 ml-5 pr-5 pl-5">
            {{'Finished' | translate}}
          </div>
          <span *ngIf="finishedTasks.length > 0"
            class="btn btn-small btn-floating green lighten-4 weg-blue-text text-darken-4">
            {{finishedTasks.length}}
          </span>
        </ng-template>
        <div class="card m-1">
          <app-queue-table [dataSourceInput]="finishedTasks"></app-queue-table>
        </div>
      </mat-tab>
      <mat-tab *ngIf="!searching">
        <ng-template mat-tab-label>
          <div class="mr-5 ml-5 pr-5 pl-5">
            {{'Canceled' | translate}}
          </div>
          <span *ngIf="canceledTasks.length > 0" class="btn btn-small btn-floating red lighten-1">
          {{canceledTasks.length}} </span>
        </ng-template>
        <div class="card m-1">
          <app-queue-table [dataSourceInput]="canceledTasks"></app-queue-table>
        </div>
      </mat-tab>
      <mat-tab *ngIf="searching" class="p-4">
        <ng-template mat-tab-label>
          <div class="mr-5 ml-5 pr-5 pl-5">
            {{'Searching' | translate}}
          </div>
          <span *ngIf="search > 0" class="btn btn-small btn-floating disabled"> {{search}} </span>
        </ng-template>
        <div class="card p-3">
          <app-queue-table [dataSourceInput]="canceledTasks"></app-queue-table>
        </div>
      </mat-tab>
    </mat-tab-group>
  </div>
</div>

父组件(TypeScript):

import { Component, OnInit, ViewChild } from '@angular/core'
import { MatTabGroup, MatTabHeaderPosition } from '@angular/material/tabs';
import { Router } from '@angular/router';
import { ModTask } from 'src/app/core/models/modTask.model';
import { UserService } from 'src/app/core/services/user.service';
import { ModTaskService } from 'src/app/shared/services/modTask.service';

@Component({
  selector: "app-home",
  templateUrl: "./home.component.html",
  styleUrls: ["./home.component.css"]
})
export class HomeComponent implements OnInit{

  public tasks: ModTask[]
  public openTasks: ModTask[]
  public inProgressTasks: ModTask[]
  public finishedTasks: ModTask[]
  public canceledTasks: ModTask[]

  public searching = false;
  public open: number = 0;
  public inProgress: number = 0;
  public finished: number = 0;
  public canceled: number = 0;
  public working: number = 0;
  public search: number = 0;
  public selectedTab: number;
  public coordinator: string

  private cacheName = "165116511s1a";

  @ViewChild('tabGroup') tabGroup: MatTabGroup;

  constructor(
    private router: Router,
    private modTaskService: ModTaskService,
    private userService: UserService
  ) {}

  async ngOnInit(): Promise<void> {
    this.userService.getLoggedUser().subscribe(user => { this.coordinator = user.userLogin })
    this.tasks = await this.modTaskService.getByCoordinator(this.coordinator)
    this.openTasks = this.tasks.filter(tasks => tasks.status.status === "Open")
    this.inProgressTasks = this.tasks.filter(tasks => tasks.status.status === "In Progress")
    this.finishedTasks = this.tasks.filter(tasks => tasks.status.status === "Finished")
    this.canceledTasks = this.tasks.filter(tasks => tasks.status.status === "Canceled")
    console.log(this.openTasks)
  }

  async ngAfterViewInit() {
    console.log('atualizado')
  }

  setTab(tab: number) {
    this.ngAfterViewInit()
  }

  // ACTIONS =========================================================
  setSearch(event: boolean) {
    this.searching = event;
    localStorage.setItem(this.cacheName + "as", event.toString());
  }

  // QUEUE COUNTS ====================================================
  setResultLength(type: number, resultLength: number = 0) {
    switch (type) {
      case 1:
        this.open = resultLength;
        break;
      case 2:
        this.inProgress = resultLength;
        break;
      case 3:
        this.finished = resultLength;
        break;
      case 4:
        this.canceled = resultLength;
        break;
      case 5:
        this.open = 0;
        this.inProgress = 0;
        this.finished = 0;
        this.search = resultLength;
        break;
    }
  }
}

子组件(HTML):

<div class="row fadeIn animated m-0 p-0 table-wrapper" style="min-height:480px">
  <!-- <div class="col s12 vertical-center" style="height:100%" *ngIf="dataSource.length === 0">
    <span class="material-icons large grey-text text-lighten-3"
        style="margin-right: auto; margin-left: auto;">inbox</span>
    </div> -->
    <!--COM RESULTADOS-->
    <table mat-table [dataSource]="dataSourceInput">
      <ng-container matColumnDef="id">
        <th mat-header-cell *matHeaderCellDef> ID </th>
        <td mat-cell *matCellDef="let task" (click)="openRequest(task)"> {{task.id}} </td>
      </ng-container>
      <ng-container matColumnDef="branch">
        <th mat-header-cell *matHeaderCellDef> Branch </th>
        <td mat-cell *matCellDef="let task" (click)="openRequest(task)"> {{task.branchId}} </td>
      </ng-container>
      <ng-container matColumnDef="createdBy">
        <th mat-header-cell *matHeaderCellDef> Created By </th>
        <td mat-cell *matCellDef="let task" (click)="openRequest(task)"> {{task.creatorUserName}} </td>
      </ng-container>
      <ng-container matColumnDef="salesDocument">
        <th mat-header-cell *matHeaderCellDef> Sales Document </th>
        <td mat-cell *matCellDef="let task" (click)="openRequest(task)"> {{task.salesDocument}} </td>
      </ng-container>
      <ng-container matColumnDef="createdAt">
        <th mat-header-cell *matHeaderCellDef> Created At </th>
        <td mat-cell *matCellDef="let task" (click)="openRequest(task)"> {{task.createdAt}} </td>
      </ng-container>
      <ng-container matColumnDef="updatedAt">
        <th mat-header-cell *matHeaderCellDef> Updated At </th>
        <td mat-cell *matCellDef="let task" (click)="openRequest(task)"> {{task.updatedAt}} </td>
      </ng-container>
      <ng-container matColumnDef="target">
        <th mat-header-cell *matHeaderCellDef> Target </th>
        <td mat-cell *matCellDef="let task" (click)="openRequest(task)"> {{task.target}} </td>
      </ng-container>

      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>
    <mat-paginator #paginator [pageSizeOptions]="[5, 10, 20]"
                 showFirstLastButtons
                 aria-label="Select page of periodic elements">
    </mat-paginator>
</div>

子组件(TypeScript):

import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
import { Router } from '@angular/router'
import { ModTask } from 'src/app/core/models/modTask.model'
import { QueueTable } from 'src/app/shared/components/queue-table/queue-table.component'
import {MatPaginator} from '@angular/material/paginator'
import { MatTableDataSource } from '@angular/material/table'

@Component({
  selector: 'app-queue-table',

  templateUrl: './task-queue.component.html',
  styleUrls: ['./task-queue.component.css']
})
export class QueueTableComponent {

  @Input() public dataSourceInput: ModTask[]

  displayedColumns: string[] = ['id', 'branch', 'createdBy', 'salesDocument', 'createdAt', 'updatedAt', 'target']

  ngAfterViewInit(): void {
    console.log(this.dataSourceInput)
  }

  constructor(
    private router: Router
  ) {
  }

  public openRequest(modTask: ModTask) {
    this.router.navigate([`moduleTask/process/${modTask.id}`])
  }
}

如您所见,我在父组件的API中获取数据,执行需要完成的过滤,并将此数据作为子组件的输入。在子组件中,我使用Angular的Material Table在屏幕上显示此数据。数据按照我的意愿显示,但当console.log执行ngAfterViewInit中的(),它返回undefined,我需要对这个数据做一些工作来过滤,但是我不能,因为它被设置为undefined,甚至在屏幕上显示数据。
我想知道为什么会发生这种情况,以及可以做些什么来在浏览器控制台中正确返回数据。
我想知道为什么会发生这种情况,以及如何在浏览器控制台中正确地返回数据。我尝试了几种不同的方式使用@Input(),但都没有成功。

oo7oh9g9

oo7oh9g91#

你用来输入的值是异步获取的,你的输入数据会显示出来,因为在设置了对这个数据的异步调用之后,运行更改检测并将其更新为返回值。您可以通过将子生命周期挂接从ngAfterViewInit更改为(运行一次)到ngAfterViewChecked(每次视图检查后运行)。您将看到它现在将记录undefined(您的初始值),然后记录更新后的视图值。
一个简单的解决方法是在孩子身上放置一个ngIf,直到任务设置完成,例如<app-queue-table *ngIf="tasks" [dataSourceInput]="inProgressTasks"></app-queue-table>
这样,只有当数据已经存在时,子对象才会被示例化,因此在输入中传递的初始值将始终被定义。注意,如果您使用了严格的TypeScript检查并相应地键入了变量,IDE将警告您正在尝试设置值“X|未定义”到只应该是“X”的东西。

nukf8bse

nukf8bse2#

在使用@Input时,可以使用ngOnChanges事件捕获事件。

export class QueueTableComponent implements OnChanges{
    ngOnChanges(changes: SimpleChanges): void {
        if (changes['dataSourceInput']) {
           console.log(this.dataSourceInput)
        }
    }
}

这样,@Input中变量的所有更改都将被监听,并将在属性dataSourceInput的“changes”对象中找到,该对象是从父组件接收的列表。

fd3cxomn

fd3cxomn3#

尝试创建public openTasks = new MatTableDataSource<ModTask>();这样的任务变量,并设置this.openTasks.data = this.tasks.filter(tasks => tasks.status.status === "Open")这样的数据。

相关问题