Progress binding is not updating while uploading

Since it requires cordova I guess a code pen will not work. So I went ahead and created a repo for you to check.

REPO => deleted

Just take some pictures with the camera and press start uploading. The view does not update, but if you check the console with chrome inspect the logs show progress is being made. The images will be uploaded to a test API of mine so dont worry about that. I’ve tested it on an android samsung galaxy S7 edge with android 6.0.1.

I hope you can help me because this shit is messing me up :cry:

Hmm, so what I’m guess is that the file transfer happens outside of angular’s zones, so it doesn’t know how to update the bindings.

At the moment, the file transfer plugin isn’t in ionic-native, but there’s an issue open for it.

You could wait for that to get added, or you make a PR with the wrapper in place.

Hmm. Any idea when ‘soon’ is? :slight_smile: Days? Weeks? Months?

I guess that most probably the problem that you’re observing is caused by this:

however you might also check if something like this will work:

            ft.onprogress = e => this.onProgress(e);

I already had a similar problem and it was caused by the fact that the value of this inside the handler was set to the global Window object instead of the object itself.

@iignatov l’ll try that tonight when I come home. Am I correct if I say the e is an event object? If so what event is it?

If you look at my onProgress function, it already recieves an event.

onProgress = (progressEvent: ProgressEvent) : void => {
        if (progressEvent.lengthComputable) {
            this.progress = Math.round((progressEvent.loaded / progressEvent.total) * 100);
            console.log("Progress: ", this.progress);
        }
    }

@dtaalbers Yes, e is the event object. It’s of type ProgressEvent. You can also write it this way:

            ft.onprogress = (e: ProgressEvent) => this.onProgress(e);

I get it thanks :slight_smile:

fyi; I don’t have the problem of a missing event. My current code as in

onProgress = (progressEvent: ProgressEvent) : void => { ... }

has an event there. I have no problem accesssing it.

Could your suggestion give the current scope (as in this) to the onProgress function? Because that sounds nice :stuck_out_tongue:

If the issue that you’re observing is caused by the (unexpected) value of this then the change that I suggested might resolve it. I created a simple (maybe too oversimplified) test to illustrate this. You can check it out in this demo environment.

Sadly I can’t get it work. Probably have to wait until this plugin goes ionic native. For now I used filthy jquery to update the DOM elements.

Thanks for the help boys!

if you need update DOM you can use native js. No need to clutter up the code.
However, you can read about zone.js with Angular 2 for the DOM forcing update. Google it.

1 Like

Thank you for the hint. I’ve managed to get it to work without JQuery and or native js. I’ve updated my example (with the ionic-native wrapper) here :slight_smile:

1 Like

Hi all, i solved case with progress bar for Transfer.upload, with synchronouse upload of lots of files and for each file own progressbar.

Some structure for files to upload:
export interface processedFile {
path?:string, //dir of files lib
size?:number, //size of file
file?:string,
progress?:string, //% of upload
done?:boolean //flag with responce from server about md5 checksum is ok
}
export interface processedFiles extends Array{} //array of files to upload

public processedFiles:processedFiles = [] //array of files to upload

this.uploadTo(this.processedFiles[i], userData) //start to upload file of files array

onProgress(item, progress) { //item - here will be item of files array and progress digit
    item.progress = progress; //
}

uploadTo(item:processedFile, userData: AccountData) {
    return new Promise((resolve, reject) => {
        let fdata: Url = {file:item.file, path:item.path}; // url model
        let fileTransfer = new Transfer();
        fileTransfer.onProgress((progressEvent: any ) => {
            if (progressEvent.lengthComputable) {
                let progress = Math.round((progressEvent.loaded / progressEvent.total) * 100);
                this.onProgress(item, progress) //**here trick, which allow progress to get visibility**
            }
        });
        fileTransfer.upload(this.ops.getFilenameFromURL(fdata), this.vars.premoveexpertpl, {
            fileName: fdata.file,
            params: {f: "upload", u: userData.username, p: userData.password}
        }, true).then((ret) => {
            let res: FileUploadResult = <FileUploadResult>ret;
            let url:Url = this.ops.getFileNameFromPath(res.headers['file']);

//…some not interesting code

        }, (err) => {

//…some not interesting code
})
})
}

I fixed this by surrounding my progress function with zone.run:

import {NgZone} from '@angular/core';

  constructor(
    ...
    public _zone: NgZone) {
  }
      fileTransfer.onProgress((e) => {
        this._zone.run(() =>             
            myObj.uploadPercentage = (e.lengthComputable) ?  Math.floor(e.loaded / e.total * 100) : -1;          
        });
      });
6 Likes

Thanks, this works for me

Why onProgress not show in IOS ? :worried:

For anyone interested, I have a full upload example in this example app. You can download the repo and try it on your own phone!

1 Like

[quote=“Daveshirman, post:17, topic:47647”]
NgZone
Thanks Dude. Worked for me. Could you please explain what’s going on here when using ngZone.

Honestly I haven’t looked into it deeply. It’s obviously to do with how
Angular 2 tracks changes in state. That’s all I can give you! Glad it
helped.

Surely file transfer has been updated to properly work within Angular’s zone, yes?

It’s normally a warning sign when you have to start manually dealing with NgZone.

1 Like

Excellent, it worked for me