简体   繁体   English

Aurelia BindingEngine属性观察者不会触发

[英]Aurelia BindingEngine propertyObserver does not fire

I have an Aurelia file upload controller where I would like to observe the progress property of any object that is added to the array uploadedFiles . 我有一个Aurelia文件上传控制器,在这里我想观察添加到数组uploadedFiles数组中任何对象的progress属性。 First off, my HTML template looks like this: 首先,我的HTML模板如下所示:

<input type="file" name="files" files.bind="fileList" multiple change.delegate="fileSelected($event)" />

This is the controller (simplified). 这是控制器(简体)。 The method fileSelected gets fired when the user selects a file. 用户选择文件时,将触发fileSelected方法。

import {BindingEngine, inject} from 'aurelia-framework';
import {HttpService} from '../../services/http-service';
import {UploadedFile} from '../../models/uploaded-file';

@inject(BindingEngine)
export class FileUploader {
  httpClient: HttpService;
  fileList: FileList;
  uploadedFiles: UploadedFile[];

  constructor(bindingEngine) {
    this.bindingEngine = bindingEngine;
    this.httpClient = new HttpService();
    this.uploadedFiles = [];
  }

  fileSelected(): void {
    if (this.fileList) {
      // Convert the FileList object into an array of UploadedFile objects because the Aurelia template engine cannot iterate over a 'FileList' object with 'repeat.for'.
      for (let i = 0; i < this.fileList.length; i++) {
        let file = this.fileList.item(i);
        let uploadedFile = new UploadedFile();
        uploadedFile.file = file;

        // Subscribe to changes of the 'progress' property of every UploadedFile.
        uploadedFile.subscription = this.bindingEngine
          .propertyObserver(uploadedFile, 'progress')
          .subscribe((newValue, oldValue) => {
            console.log('Progress changed from ' + oldValue + ' to ' + newValue);
          });

        this.uploadedFiles.push(uploadedFile);

        // Start off the file upload itself.
        this.httpClient.uploadRequest('files', file, uploadedFile.updateProgress)
          .then((httpResponse) => {
            // File uploaded successfully!
          });
      }
    }
  }
}

I do this because the progress update comes from an external event and therefore the binding from the controller back to the template does not work out of the box (because not every object is observed for performance reasons). 我这样做是因为进度更新来自外部事件,因此从控制器到模板的绑定无法立即使用(因为出于性能方面的原因并不是每个对象都被观察到)。

Here's the UploadedFile class: 这是UploadedFile类:

export class UploadedFile {
  file: File;
  uploaded: boolean;
  totalBytes: number;
  uploadedBytes: number;
  progress: number;
  subscription: any;

  constructor() {
    this.uploaded = false;
    this.progress = 0;
  }

  updateProgress(event: ProgressEvent) {
    this.totalBytes = event.total;
    this.uploadedBytes = event.loaded;

    this.progress = this.uploadedBytes / this.totalBytes * 100;
    console.log('Progress is ' + this.progress + ' %.');
  }
}

Here's what the upload request looks like (note the withProgressCallback line): 这是上传请求的样子(请注意withProgressCallback行):

import {HttpClient} from 'aurelia-http-client';

export class HttpService {
  backendUrl: string;
  httpClient: HttpClient;

  constructor() {
    // ...
  }

  uploadRequest(url: string, file: File, progressCallback: any): Promise<any> {
    let formData = new FormData();
    formData.append('file', file);

    return this.httpClient.createRequest(url)
      .asPost()
      .withContent(formData)
      .withCredentials(true)
      .withProgressCallback(progressCallback) // This adds the progress callback.
      .send();
  }
}

Now there is obviously something I'm doing wrong, because the property change event never fires, even though I can see the progress updates in the browser console in the UploadedFile class. 现在显然我在做错事,因为即使我可以在UploadedFile类的浏览器控制台中看到进度更新,也不会触发属性更改事件。

Can someone tell me what's wrong with the propertyObserver subscription? 有人可以告诉我propertyObserver订阅出了什么问题吗?

When it comes to upload progress, you need to ensure it's trackable by browser. 在上传进度时,您需要确保浏览器可以跟踪它。 Secondly, your uploadRequest in HttpService doesn't preserve execution context, which means updateProgress won't be called on correct instances of UploadedFile class. 其次,您在HttpService中的uploadRequest不会保留执行上下文,这意味着不会在UploadedFile类的正确实例上调用updateProgress Probably you need to do something like this: 可能您需要执行以下操作:

this.httpClient.uploadRequest('files', file, () => uploadedFile.updateProgress() })
      .then((httpResponse) => {
        // File uploaded successfully!
      });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM