У меня есть компонент загрузки, где пользователь может выбирать файлы.Я рефакторинг на onPush
, но я испытываю странное поведение:
export class FileUploadComponent implements OnInit, OnDestroy {
files$: BehaviorSubject<FileToUpload[]> = new BehaviorSubject([]);
readonly files: Observable<FileToUpload[]> = this.files$.asObservable();
fileStateSubscription: Subscription;
uploadCandidates$: Subscription;
activeFiles: FileToUpload[];
canUpload: boolean;
isUploading: boolean;
constructor(
private uploadService: UploadService
) {}
ngOnInit() {
this.uploadService.study$.take(1).subscribe((study) => (this.study = study));
this.uploadService.currentUser$.take(1).subscribe((currentUser) => (this.currentUser = currentUser));
this.fileStateSubscription = this.files.subscribe((files) => {
this.activeFiles = files.filter((f) => f.state !== FileUpLoadState.success);
this.canUpload = files.length > 0 && files.every((f) => f.state === FileUpLoadState.new && f.isValid);
this.isUploading = files.length > 0 && files.some((f) => f.state === FileUpLoadState.uploading);
});
}
async upload(event: Event) {
const fileList: FileList = (event.target as HTMLInputElement).files;
this.uploadActions.clearUploadCandidates();
if (!fileList.length) {
return;
}
let files: FileToUpload[];
files = await this.uploadService.upload(this.files$.getValue(), fileList);
this.files$.next(this.files$.getValue().concat(files));
setTimeout(() => {
this.uploadButtonRef.fileInputRef.nativeElement.value = '';
});
}
}
При первом нажатии на шаблон отображается 0
, хотя fileState.activeFiles
имеет длину 1
, а следующийкогда я нажимаю, отображается 1
, хотя fileState.activeFiles
имеет длину 2
.
Если я удаляю changeDetection: ChangeDetectionStrategy.OnPush
, тогда все работает, как ожидалось.
Если изменить мойвведите ChangeDetectorRef
, а затем измените мою подписку следующим образом:
this.fileStateSubscription = this.files$.subscribe((files) => {
this.activeFiles = files.filter((f) => f.state !== FileUpLoadState.success);
this.canUpload = files.length > 0 && files.every((f) => f.state === FileUpLoadState.new && f.isValid);
this.isUploading = files.length > 0 && files.some((f) => f.state === FileUpLoadState.uploading);
this._changeDetector.markForCheck();
});
Тогда это сработает, но я думаю, что это побеждает цель, если мне нужно явно пометить каждое изменение.
Это потому, что код, который вызывает next
, является функцией async
?
Что я делаю не так?