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();
}
到目前为止,我正在使用多个文件上传组件,这就是我所拥有的:
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();
}