-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
5,056 additions
and
5,184 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"editor.formatOnSave": true, | ||
"editor.codeActionsOnSave": { | ||
"source.fixAll.eslint": "explicit", | ||
"source.fixAll.stylelint": "explicit" | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,29 @@ | ||
/* eslint-disable @angular-eslint/no-output-native */ | ||
import { Directive, ElementRef, Input, EventEmitter, Output, NgZone, OnDestroy, OnInit } from '@angular/core'; | ||
import { Directive, ElementRef, NgZone, OnInit, inject, DestroyRef, input } from '@angular/core'; | ||
import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; | ||
import { filter, fromEvent, Observable, Subject, takeUntil } from 'rxjs'; | ||
import { filter, fromEvent, Observable, Subject } from 'rxjs'; | ||
import { FileSaverOptions } from 'file-saver'; | ||
import { FileSaverService } from './filesaver.service'; | ||
import { outputFromObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop'; | ||
|
||
@Directive({ | ||
selector: '[fileSaver]', | ||
exportAs: 'fileSaver', | ||
standalone: true, | ||
}) | ||
export class FileSaverDirective implements OnInit, OnDestroy { | ||
@Input() method = 'GET'; | ||
@Input() http?: Observable<HttpResponse<Blob>>; | ||
@Input() query: any; | ||
@Input() header: any; | ||
@Input({ required: true }) url!: string; | ||
@Input() fileName?: string; | ||
@Input() fsOptions?: FileSaverOptions; | ||
@Output() readonly success = new EventEmitter<HttpResponse<Blob>>(); | ||
@Output() readonly error = new EventEmitter<any>(); | ||
export class FileSaverDirective implements OnInit { | ||
readonly method = input('GET'); | ||
readonly http = input<Observable<HttpResponse<Blob>>>(); | ||
readonly query = input<any>(); | ||
readonly header = input<any>(); | ||
readonly url = input.required<string>(); | ||
readonly fileName = input<string>(); | ||
readonly fsOptions = input<FileSaverOptions>(); | ||
private successEmitter = new Subject<HttpResponse<Blob>>(); | ||
readonly success = outputFromObservable(this.successEmitter); | ||
private errorEmitter = new Subject<any>(); | ||
readonly error = outputFromObservable(this.errorEmitter); | ||
|
||
private readonly destroy$ = new Subject<void>(); | ||
private readonly d$ = inject(DestroyRef); | ||
|
||
constructor( | ||
private ngZone: NgZone, | ||
|
@@ -38,12 +40,8 @@ export class FileSaverDirective implements OnInit, OnDestroy { | |
this.ngZone.runOutsideAngular(() => this.setupClickListener()); | ||
} | ||
|
||
ngOnDestroy(): void { | ||
this.destroy$.next(); | ||
} | ||
|
||
private getName(res: HttpResponse<Blob>) { | ||
return decodeURI(this.fileName || res.headers.get('filename') || res.headers.get('x-filename') || ''); | ||
return decodeURI(this.fileName() || res.headers.get('filename') || res.headers.get('x-filename') || ''); | ||
} | ||
|
||
setDisabled(status: boolean): void { | ||
|
@@ -56,54 +54,40 @@ export class FileSaverDirective implements OnInit, OnDestroy { | |
fromEvent(this.el.nativeElement, 'click') | ||
.pipe( | ||
filter(() => this.fss.isFileSaverSupported), | ||
takeUntil(this.destroy$), | ||
takeUntilDestroyed(this.d$), | ||
) | ||
.subscribe(() => { | ||
let req = this.http; | ||
let req = this.http(); | ||
|
||
if (!req) { | ||
let params = new HttpParams(); | ||
const query = this.query || {}; | ||
const query = this.query() || {}; | ||
for (const item in query) { | ||
params = params.set(item, query[item]); | ||
} | ||
|
||
req = this.httpClient.request(this.method, this.url, { | ||
req = this.httpClient.request(this.method(), this.url(), { | ||
observe: 'response', | ||
responseType: 'blob', | ||
headers: this.header, | ||
headers: this.header(), | ||
params, | ||
}); | ||
} | ||
|
||
this.setDisabled(true); | ||
|
||
req.pipe(takeUntil(this.destroy$)).subscribe({ | ||
req.pipe(takeUntilDestroyed(this.d$)).subscribe({ | ||
next: (response) => { | ||
if (response.status !== 200 || response.body!.size <= 0) { | ||
this.emitIfHasObservers(this.error, response); | ||
this.errorEmitter.next(response); | ||
return; | ||
} | ||
this.fss.save(response.body, this.getName(response), undefined, this.fsOptions); | ||
this.emitIfHasObservers(this.success, response); | ||
this.fss.save(response.body, this.getName(response), undefined, this.fsOptions()); | ||
this.successEmitter.next(response); | ||
}, | ||
error: (error) => this.emitIfHasObservers(this.error, error), | ||
error: (error) => this.errorEmitter.next(error), | ||
complete: () => this.setDisabled(false), | ||
}); | ||
}); | ||
} | ||
|
||
private emitIfHasObservers<T>(emitter: EventEmitter<T>, value: T): void { | ||
if (hasObservers(emitter)) { | ||
// Re-enter the Angular zone only if there're any `error` or `success` listeners | ||
// on the directive, for instance, `(success)="..."`. | ||
this.ngZone.run(() => emitter.emit(value)); | ||
} | ||
} | ||
} | ||
|
||
function hasObservers<T>(subject: Subject<T>): boolean { | ||
// Note: The `observed` property is available only in [email protected], which means it's | ||
// not available for users running the lower version. | ||
return subject.observed ?? subject.observers.length > 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"name": "ngx-filesaver", | ||
"version": "18.0.0", | ||
"version": "19.0.0", | ||
"description": "Simple file save with FileSaver.js", | ||
"repository": { | ||
"type": "git", | ||
|
@@ -29,40 +29,41 @@ | |
"release:next": "npm run build && cd publish && npm publish --access public --tag next" | ||
}, | ||
"dependencies": { | ||
"@angular/animations": "^18.0.0", | ||
"@angular/common": "^18.0.0", | ||
"@angular/compiler": "^18.0.0", | ||
"@angular/core": "^18.0.0", | ||
"@angular/forms": "^18.0.0", | ||
"@angular/platform-browser": "^18.0.0", | ||
"@angular/platform-browser-dynamic": "^18.0.0", | ||
"@angular/router": "^18.0.0", | ||
"@angular/animations": "^19.0.0", | ||
"@angular/common": "^19.0.0", | ||
"@angular/compiler": "^19.0.0", | ||
"@angular/core": "^19.0.0", | ||
"@angular/forms": "^19.0.0", | ||
"@angular/platform-browser": "^19.0.0", | ||
"@angular/platform-browser-dynamic": "^19.0.0", | ||
"@angular/router": "^19.0.0", | ||
"rxjs": "~7.8.0", | ||
"tslib": "^2.3.0", | ||
"zone.js": "~0.14.3" | ||
"zone.js": "~0.15.0" | ||
}, | ||
"devDependencies": { | ||
"@angular-devkit/build-angular": "^18.0.4", | ||
"@angular-eslint/builder": "^18.0.0", | ||
"@angular-eslint/eslint-plugin": "^18.0.0", | ||
"@angular-eslint/eslint-plugin-template": "^18.0.0", | ||
"@angular-eslint/schematics": "^18.0.0", | ||
"@angular-eslint/template-parser": "^18.0.0", | ||
"@angular/cli": "^18.0.4", | ||
"@angular/compiler-cli": "^18.0.0", | ||
"@types/file-saver": "^2.0.5", | ||
"@angular-devkit/build-angular": "^19.0.1", | ||
"@angular-eslint/builder": "^18.4.1", | ||
"@angular-eslint/eslint-plugin": "^18.4.1", | ||
"@angular-eslint/eslint-plugin-template": "^18.4.1", | ||
"@angular-eslint/schematics": "^18.4.1", | ||
"@angular-eslint/template-parser": "^18.4.1", | ||
"@angular/cli": "^19.0.1", | ||
"@angular/compiler-cli": "^19.0.0", | ||
"@types/file-saver": "^2.0.7", | ||
"@types/jasmine": "~5.1.0", | ||
"@typescript-eslint/eslint-plugin": "^7.13.0", | ||
"@typescript-eslint/parser": "^7.13.0", | ||
"@typescript-eslint/eslint-plugin": "^8.15.0", | ||
"@typescript-eslint/parser": "^8.15.0", | ||
"eslint": "^8.53.0", | ||
"file-saver": "^2.0.5", | ||
"jasmine-core": "~5.1.0", | ||
"jasmine-core": "~5.4.0", | ||
"karma": "~6.4.0", | ||
"karma-chrome-launcher": "~3.2.0", | ||
"karma-coverage": "~2.2.0", | ||
"karma-jasmine": "~5.1.0", | ||
"karma-jasmine-html-reporter": "~2.1.0", | ||
"ng-packagr": "^18.0.0", | ||
"typescript": "~5.4.2" | ||
} | ||
"ng-packagr": "^19.0.1", | ||
"typescript": "~5.6.2" | ||
}, | ||
"packageManager": "[email protected]" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.