以编程方式更改输入类型文件的值?

时间:2019-03-13 12:03:04

标签: javascript html input filelist

我正在尝试生成一些代码,可以在整个网站上重复使用,这些代码本质上是经过一些验证的照片选择器/选择器。这是我的代码:

Widget Function(Widget) addSpacing(double space) => (Widget child) =>
  Container(
    margin: EdgeInsets.only(right: space),
    child: child,
  );

发生的事情是,当我第一次选择某些图像时,显示缩略图,并且有效文件列表class PhotoPicker { constructor(element) { this.element = element; //Creating needed HTML Markup this.createMarkUp(); //FileList of valid data. this.validFiles = new DataTransfer(); //Initialise Picker. this.input.onchange = () => { this.updateOutput(); this.output.files = this.validFiles.files; } } updateOutput() { const files = Array.from(this.input.files); files.forEach((file) => { let reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => { photo = this.createPhotoThumb({ url : reader.result, name: file.name, size: file.size }); if (this.validatePhoto(file)) { this.validFiles.items.add(file); }; }; }); } createMarkUp() { //Creating needed HTML Markup } createPhotoThumb(data = {}) { //Creating a photo thumbnail for preview } validatePhoto(photo) { //Validating the photo } } 得到更新,但是 NOT 我计划发送到服务器this.validFiles.files的最终列表,但是,第二次尝试成功了!最终列表将使用第一个选择的文件进行更新,而第二个 不是 的更新,依此类推。依此类推..对于每个选择,前一个选择的文件将添加到最终选择中列出但不列出最后选择的文件。

1 个答案:

答案 0 :(得分:3)

我认为问题在于您期望

reader.onload = () => {
    photo = this.createPhotoThumb({
        url : reader.result,
        name: file.name,
        size: file.size
    });
    if (this.validatePhoto(file)) {
        this.validFiles.items.add(file);
    };
};

在将有效文件分配给this.output.files之前执行get。

但是reader.onload是异步执行的,因此在将有效文件添加到有效文件数组之前,将有效文件分配给this.output.files的情况会得到执行。

您必须实现一些逻辑,以等待读者的onload处理程序的完整性。

这可能是解决方案:

class PhotoPicker
{
    constructor(element)
    {
        this.element = element;

        // Creating needed HTML Markup
        this.createMarkUp();

        // FileList of valid data.
        this.validFiles = new DataTransfer();

        // Initialise Picker.
        this.input.onchange = () => {
            this.updateOutput()
                .then(() => {
                    this.output.files = this.validFiles.files;
                });
        }
    }

    updateOutput()
    {
        const files = Array.from(this.input.files);
        const fileLoaderPromises = [];
        files.forEach((file) => {
            const promise = new Promise((resolve) => {
                let reader = new FileReader();
                reader.readAsDataURL(file);
                reader.onload = () => {
                    photo = this.createPhotoThumb({
                        url : reader.result,
                        name: file.name,
                        size: file.size
                    });
                    if (this.validatePhoto(file)) {
                        this.validFiles.items.add(file);
                    };
                    // Mark the file loader as "done"
                    resolve();
                };
            })

            // Add the promise to the list of file loader promises
            fileLoaderPromises.push(promise);
        });

        // Return a promise which resolves as soon as all file loader promises are done
        return Promise.all(fileLoaderPromises);
    }

    // ...
}