valor-software / ng2-file-upload

Easy to use Angular components for files upload
http://valor-software.github.io/ng2-file-upload/
MIT License
1.91k stars 662 forks source link

with ngrx store #547

Open BhaskaranR opened 7 years ago

BhaskaranR commented 7 years ago

We use ngrx in our application and all the communication to the service is through effect, action and store. the file upload submit breaks the current architecture. Can we wrap the entire upload queue to a store?

BhaskaranR commented 7 years ago

any update on this?

Spawnrad commented 6 years ago

Need too ;)

joelmuskwe commented 6 years ago

faced same issue too any update

Sliverb commented 6 years ago

If people are still looking for an answer to this, I found 2 hacks (Still not sure which to settle on) Both requires using a lib that is a fork of this one, but uses the new HttpClient module - https://ackerapple.github.io/angular-file/

Hack 1:

And in my subscription in the component, i pass the httpEvent to:

<ngfUploadStatus
  [(percent)] = "progress"
  [httpEvent] = "httpEvent"
></ngfUploadStatus>

which handles the progress if you want. Otherwise you can subscribe to the event and based on the type, dispatch new actions to determine if things are complete or not.

Hack 2: Make the subscription in the upload service uploadFile method and dispatch different actions based on the event type. Something similar to this:

    this.http.request(req).subscribe((event: HttpEvent<any>) => {
      switch (event.type) {
        case HttpEventType.Sent:
          console.log('Request sent!');
          break;
        case HttpEventType.ResponseHeader:
          console.log('Response header received!');
          break;
        case HttpEventType.DownloadProgress:
          const kbLoaded = Math.round(event.loaded / 1024);
          console.log(`Download in progress! ${ kbLoaded }Kb loaded`);
          break;
        case HttpEventType.Response:
          console.log('😺 Done!', event.body);
      }
    });
  }

With this path, if you want progress displayed, you can use a progress service that houses a BehaviorSubject to track things like progress% or isUploading or isDone states. The modified upload service can call .next with new values and any component interested in upload status can subscribe to the BehaviorSubject.

Not as elegant, but both should allow us to keep the ngrx architecture. Still experimenting...

Sliverb commented 6 years ago

I ended up going with a variant of hack 2. This should actually allow you to utilize ng2-file-upload as is, as long as you decouple the uploader from from the service that actually performs the upload. You can use the uploader to manage the upload queue and getting the files. Once you extract the files out, you can dispatch it out similar to what i described above. On success, you can clear the queue

This is the updated service and effect. The actions and reducer are mostly similar to the above

private _unsubscribeEmitter(): void { if (this._httpEmitter) { this._httpEmitter.unsubscribe(); this._httpEmitter = null; } }

- Effects.ts
``` Typescript
@Effect()
upload: Observable<Action> = this._actions$
    .ofType('UPLOAD')
    .switchMap((action: Action) => {
        const formData: FormData = action.payload;
        return this.uploadService.uploadFiles(formData)
            .map((uploadPercent: number) => UploadActions.UploadSucceeded(uploadPercent))
            .catch(error => Observable.of(UploadActions.UploadFailed(error)));
    });

Initially, i didn't want to dispatch actions from the service, but after looking at a few redux examples, I realize that was a baseless limitation. As long as the store is being modified only through actions (single pipeline), it should be ok to dispatch actions from anywhere. With this mentality, it became easier to manage the whole processes.

The one thing to call out, the uploadFiles method in the upload service returns an observable instantly signaling that the upload has begun. The percentage count is passed on and the same UploadProgress will continue to be called until the upload is complete/fails. This also allows us to track download progress if we like.

Hope this helps someone :)

shawnrmoss commented 6 years ago

@Sliverb any chance you have that in a repo we can look at?

Sliverb commented 6 years ago

@shawnrmoss Sadly no, its a private project I'm helping with. However, I can extract more snippets for you. Which part would you like more details on?

Sliverb commented 6 years ago

Quick update, the design we ended up going with above has been working flawlessly in case any future ngrx users stumbles upon this thread.

If more code snippets/explanation/breakdown is needed, feel free to ask away. Happy to be of service.