我有一个用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(),但都没有成功。
3条答案
按热度按时间oo7oh9g91#
你用来输入的值是异步获取的,你的输入数据会显示出来,因为在设置了对这个数据的异步调用之后,运行更改检测并将其更新为返回值。您可以通过将子生命周期挂接从
ngAfterViewInit
更改为(运行一次)到ngAfterViewChecked
(每次视图检查后运行)。您将看到它现在将记录undefined(您的初始值),然后记录更新后的视图值。一个简单的解决方法是在孩子身上放置一个ngIf,直到任务设置完成,例如
<app-queue-table *ngIf="tasks" [dataSourceInput]="inProgressTasks"></app-queue-table>
这样,只有当数据已经存在时,子对象才会被示例化,因此在输入中传递的初始值将始终被定义。注意,如果您使用了严格的TypeScript检查并相应地键入了变量,IDE将警告您正在尝试设置值“X|未定义”到只应该是“X”的东西。
nukf8bse2#
在使用@Input时,可以使用ngOnChanges事件捕获事件。
这样,@Input中变量的所有更改都将被监听,并将在属性dataSourceInput的“changes”对象中找到,该对象是从父组件接收的列表。
fd3cxomn3#
尝试创建
public openTasks = new MatTableDataSource<ModTask>();
这样的任务变量,并设置this.openTasks.data = this.tasks.filter(tasks => tasks.status.status === "Open")
这样的数据。