Angular changeDetection 未触发

Angular changeDetection not trigger

到目前为止,我正在使用多个文件上传组件,这就是我所拥有的:

upload.html

<div class="upload-file-wrapper nx-padding-x-2m">
    <ng-container *ngIf="progressFileInfo.length > 0">
        <div class="file-uploaded nx-margin-bottom-m" *ngFor="let progressFile of progressFileInfo">
            <span class="icon-document mpt-icon"></span>
            <div class="file-upload-info nx-padding-x-s">
                <p>{{ progressFile.fileName }}</p>
                <mat-progress-bar *ngIf="progressFile.value != 0 || progressFile.value != 100" mode="determinate" [value]="progressFile.value"></mat-progress-bar>
            </div>
            <button mat-icon-button>
                <span class="icon-trash-can mpt-icon nx-margin-0"></span>
        </button>
        </div>
    </ng-container>
</div>

upload.ts

@Input() serviceId!: string;
@Input() planId!: string;
@Input() set FileSelected(files: FileList) {
    if (files) {
        this.upLoadFiles(files);
    }
}
readonly progressFileInfo: any[] = [];
private readonly _destroyed$ = new Subject<void>();
constructor(
    private readonly resourceManagementService: ResourceManagementService,
    private readonly servicePlanService: ServicePlansService,
    private readonly cd: ChangeDetectorRef,
) {}

ngOnInit() {}

upLoad(index: number, file: File): void {
    this.progressFileInfo[index] = { value: 0, fileName: file.name };
    this.resourceManagementService
        .uploadAdditionalDocument(this.serviceId, this.planId, file)
        .pipe(takeUntil(this._destroyed$))
        .subscribe(
            event => {
                if (event.type === HttpEventType.UploadProgress) {
                    this.progressFileInfo[index].value = Math.round((100 * event.loaded) / event.total);
                    console.log(this.progressFileInfo);
                    this.cd.markForCheck();
                }
            },
            error => {
                this.progressFileInfo[index].value = 0;
                this.progressFileInfo[index].fileName = `Error uploading file - ${this.progressFileInfo[index].fileName}`;
            },
        );
}

upLoadFiles(files: FileList): void {
    Array.from(files).forEach((file: File, index: number) => {
        this.upLoad(index, file);
    });
}

upload.service.ts

uploadAdditionalDocument(serviceId: string, planId: string, file: File): Observable<any> {
    const url = `${this.baseUrl}/${serviceId}/plan/${planId}/api-specification/document`;

    const body: FormData = new FormData();
    body.append('file', file, file.name);

    return this.http.post<{ fileId: string }>(url, body, {
        reportProgress: true,
        responseType: 'json',
        observe: 'events',
    });
}

我的想法是跟踪每个文件上传的进度,并在进度条中显示百分比,但由于某种原因,进度条始终处于 100%,当任何请求出现错误时,我会更改将文件名称更改为 'Error uploading file ${fileName}' 并将上传百分比更改为 0,但由于某些原因 none 反映在视图中,因此由于某些原因更改检测不会在组件上触发,因为您可以看到我使用 ChangeDetectionRef 尝试手动触发变化检测,但视图没有变化,我忘了说组件正在使用 ChangeDetectionStrategy.OnPush.

不突变就试试

            if (event.type === HttpEventType.UploadProgress) {
                const c = this.progressFileInfo[index];
                c.value = Math.round((100 * event.loaded) / event.total);
                Object.assign([], this.progressFileInfo, { [index]: c });
                console.log(this.progressFileInfo);
                this.cd.detectChanges();
            }

markForCheck 不会触发变更检测。默认情况下 angular 运行 更改检测 运行 时,它将简单地标记下一次要检查的组件。

Use detectChanges() to trigger the change detection manually instead of markForCheck.

此外,由于您正在改变同一个对象,默认情况下更改检测不会 运行。 尝试更改对象 progressFileInfo 的引用而不是改变它。

if (event.type === HttpEventType.UploadProgress) {
    const exist = this.progressFileInfo;
    exist[index] = { ...exist[index], value: Math.round((100 * event.loaded) / event.total) };
    this.progressFileInfo = [...exist]
    console.log(this.progressFileInfo);
    this.cd.detectChanges();
}