Merge branch 'development' into feature/emit-event-when-file-is-selected
This commit is contained in:
@@ -37,12 +37,15 @@ Easy to use Angular2 directives for files upload ([demo](http://valor-software.g
|
|||||||
2. `authToken` - Auth token that will be applied as 'Authorization' header during file send.
|
2. `authToken` - Auth token that will be applied as 'Authorization' header during file send.
|
||||||
3. `disableMultipart` - If 'true', disable using a multipart form for file upload and instead stream the file. Some APIs (e.g. Amazon S3) may expect the file to be streamed rather than sent via a form. Defaults to false.
|
3. `disableMultipart` - If 'true', disable using a multipart form for file upload and instead stream the file. Some APIs (e.g. Amazon S3) may expect the file to be streamed rather than sent via a form. Defaults to false.
|
||||||
4. `itemAlias` - item alias (form name redefenition)
|
4. `itemAlias` - item alias (form name redefenition)
|
||||||
|
5. `formatDataFunction` - Function to modify the request body. 'DisableMultipart' must be 'true' for this function to be called.
|
||||||
|
6. `formatDataFunctionIsAsync` - Informs if the function sent in 'formatDataFunction' is asynchronous. Defaults to false.
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
- `fileOver` - it fires during 'over' and 'out' events for Drop Area; returns `boolean`: `true` if file is over Drop Area, `false` in case of out.
|
- `fileOver` - it fires during 'over' and 'out' events for Drop Area; returns `boolean`: `true` if file is over Drop Area, `false` in case of out.
|
||||||
See using in [ts demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) and
|
See using in [ts demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) and
|
||||||
[html demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.html)
|
[html demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.html)
|
||||||
|
- `onFileDrop` - it fires after a file has been dropped on a Drop Area; you can pass in `$event` to get the list of files that were dropped. i.e. `(onFileDrop)="dropped($event)"`
|
||||||
|
|
||||||
# Troubleshooting
|
# Troubleshooting
|
||||||
|
|
||||||
|
|||||||
@@ -61,8 +61,8 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let item of uploader.queue">
|
<tr *ngFor="let item of uploader.queue">
|
||||||
<td><strong>{{ item?.file?.name }}</strong></td>
|
<td><strong>{{ item?.file?.name }}</strong></td>
|
||||||
<td *ngIf="uploader.isHTML5" nowrap>{{ item?.file?.size/1024/1024 | number:'.2' }} MB</td>
|
<td *ngIf="uploader.options.isHTML5" nowrap>{{ item?.file?.size/1024/1024 | number:'.2' }} MB</td>
|
||||||
<td *ngIf="uploader.isHTML5">
|
<td *ngIf="uploader.options.isHTML5">
|
||||||
<div class="progress" style="margin-bottom: 0;">
|
<div class="progress" style="margin-bottom: 0;">
|
||||||
<div class="progress-bar" role="progressbar" [ngStyle]="{ 'width': item.progress + '%' }"></div>
|
<div class="progress-bar" role="progressbar" [ngStyle]="{ 'width': item.progress + '%' }"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -115,4 +115,16 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">Response</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
{{ response }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,9 +9,36 @@ const URL = 'https://evening-anchorage-3159.herokuapp.com/api/';
|
|||||||
templateUrl: './simple-demo.html'
|
templateUrl: './simple-demo.html'
|
||||||
})
|
})
|
||||||
export class SimpleDemoComponent {
|
export class SimpleDemoComponent {
|
||||||
public uploader:FileUploader = new FileUploader({url: URL});
|
|
||||||
public hasBaseDropZoneOver:boolean = false;
|
uploader:FileUploader;
|
||||||
public hasAnotherDropZoneOver:boolean = false;
|
hasBaseDropZoneOver:boolean;
|
||||||
|
hasAnotherDropZoneOver:boolean;
|
||||||
|
response:string;
|
||||||
|
|
||||||
|
constructor (){
|
||||||
|
this.uploader = new FileUploader({
|
||||||
|
url: URL,
|
||||||
|
disableMultipart: true, // 'DisableMultipart' must be 'true' for formatDataFunction to be called.
|
||||||
|
formatDataFunctionIsAsync: true,
|
||||||
|
formatDataFunction: async (item) => {
|
||||||
|
return new Promise( (resolve, reject) => {
|
||||||
|
resolve({
|
||||||
|
name: item._file.name,
|
||||||
|
length: item._file.size,
|
||||||
|
contentType: item._file.type,
|
||||||
|
date: new Date()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.hasBaseDropZoneOver = false;
|
||||||
|
this.hasAnotherDropZoneOver = false;
|
||||||
|
|
||||||
|
this.response = '';
|
||||||
|
|
||||||
|
this.uploader.response.subscribe( res => this.response = res );
|
||||||
|
}
|
||||||
|
|
||||||
public fileOverBase(e:any):void {
|
public fileOverBase(e:any):void {
|
||||||
this.hasBaseDropZoneOver = e;
|
this.hasBaseDropZoneOver = e;
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ import { FileSelectDirective, FileDropDirective, FileUploader } from 'ng2-file-u
|
|||||||
1. `url` - URL of File Uploader's route
|
1. `url` - URL of File Uploader's route
|
||||||
2. `authToken` - auth token that will be applied as 'Authorization' header during file send.
|
2. `authToken` - auth token that will be applied as 'Authorization' header during file send.
|
||||||
3. `disableMultipart` - If 'true', disable using a multipart form for file upload and instead stream the file. Some APIs (e.g. Amazon S3) may expect the file to be streamed rather than sent via a form. Defaults to false.
|
3. `disableMultipart` - If 'true', disable using a multipart form for file upload and instead stream the file. Some APIs (e.g. Amazon S3) may expect the file to be streamed rather than sent via a form. Defaults to false.
|
||||||
|
4. `itemAlias` - item alias (form name redefenition)
|
||||||
|
5. `formatDataFunction` - Function to modify the request body. 'DisableMultipart' must be 'true' for this function to be called.
|
||||||
|
6. `formatDataFunctionIsAsync` - Informs if the function sent in 'formatDataFunction' is asynchronous. Defaults to false.
|
||||||
|
|
||||||
## FileDrop API
|
## FileDrop API
|
||||||
|
|
||||||
@@ -37,3 +40,4 @@ import { FileSelectDirective, FileDropDirective, FileUploader } from 'ng2-file-u
|
|||||||
- `fileOver` - it fires during 'over' and 'out' events for Drop Area; returns `boolean`: `true` if file is over Drop Area, `false` in case of out.
|
- `fileOver` - it fires during 'over' and 'out' events for Drop Area; returns `boolean`: `true` if file is over Drop Area, `false` in case of out.
|
||||||
See using in [ts demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) and
|
See using in [ts demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) and
|
||||||
[html demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.html)
|
[html demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.html)
|
||||||
|
- `onFileDrop` - it fires after a file has been dropped on a Drop Area; you can pass in `$event` to get the list of files that were dropped. i.e. `(onFileDrop)="dropped($event)"`
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
"declaration": false,
|
"declaration": false,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"noEmitHelpers" :true,
|
"noEmitHelpers": false,
|
||||||
"lib": ["es6", "dom"],
|
"lib": ["es6", "dom"],
|
||||||
"types": [
|
"types": [
|
||||||
"jasmine",
|
"jasmine",
|
||||||
|
|||||||
@@ -6,31 +6,29 @@ const customLaunchers = require('./scripts/sauce-browsers').customLaunchers;
|
|||||||
module.exports = function (config) {
|
module.exports = function (config) {
|
||||||
const configuration = {
|
const configuration = {
|
||||||
basePath: '',
|
basePath: '',
|
||||||
frameworks: ['jasmine', 'angular-cli'],
|
frameworks: ['jasmine', '@angular/cli'],
|
||||||
plugins: [
|
plugins: [
|
||||||
require('karma-jasmine'),
|
require('karma-jasmine'),
|
||||||
require('karma-chrome-launcher'),
|
require('karma-chrome-launcher'),
|
||||||
require('karma-remap-istanbul'),
|
require('karma-coverage-istanbul-reporter'),
|
||||||
require('angular-cli/plugins/karma')
|
require('@angular/cli/plugins/karma')
|
||||||
],
|
],
|
||||||
files: [
|
files: [
|
||||||
{pattern: './scripts/test.ts', watched: false}
|
{pattern: './scripts/test.ts', watched: false}
|
||||||
],
|
],
|
||||||
preprocessors: {
|
preprocessors: {
|
||||||
'./scripts/test.ts': ['angular-cli']
|
'./scripts/test.ts': ['@angular/cli']
|
||||||
},
|
},
|
||||||
remapIstanbulReporter: {
|
coverageIstanbulReporter: {
|
||||||
reports: {
|
reports: [ 'html', 'lcovonly' ],
|
||||||
html: 'coverage',
|
fixWebpackSourcePaths: false
|
||||||
lcovonly: './coverage/coverage.lcov'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
angularCli: {
|
angularCli: {
|
||||||
config: './angular-cli.json',
|
config: './angular-cli.json',
|
||||||
environment: 'dev'
|
environment: 'dev'
|
||||||
},
|
},
|
||||||
reporters: config.angularCli && config.angularCli.codeCoverage
|
reporters: config.angularCli && config.angularCli.codeCoverage
|
||||||
? ['dots', 'karma-remap-istanbul']
|
? ['dots', 'coverage-istanbul']
|
||||||
: ['dots'],
|
: ['dots'],
|
||||||
port: 9876,
|
port: 9876,
|
||||||
colors: true,
|
colors: true,
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
"@angular/core": "^2.3.1 || >=4.0.0"
|
"@angular/core": "^2.3.1 || >=4.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@angular/cli": "1.0.0",
|
||||||
"@angular/common": "2.4.3",
|
"@angular/common": "2.4.3",
|
||||||
"@angular/compiler": "2.4.3",
|
"@angular/compiler": "2.4.3",
|
||||||
"@angular/compiler-cli": "2.4.3",
|
"@angular/compiler-cli": "2.4.3",
|
||||||
@@ -64,7 +65,6 @@
|
|||||||
"@types/marked": "0.0.28",
|
"@types/marked": "0.0.28",
|
||||||
"@types/node": "7.0.0",
|
"@types/node": "7.0.0",
|
||||||
"@types/webpack": "^2.2.1",
|
"@types/webpack": "^2.2.1",
|
||||||
"@angular/cli": "1.0.0",
|
|
||||||
"bootstrap": "3.3.7",
|
"bootstrap": "3.3.7",
|
||||||
"chokidar-cli": "1.2.0",
|
"chokidar-cli": "1.2.0",
|
||||||
"classlist-polyfill": "1.0.3",
|
"classlist-polyfill": "1.0.3",
|
||||||
@@ -87,6 +87,7 @@
|
|||||||
"karma": "1.4.0",
|
"karma": "1.4.0",
|
||||||
"karma-chrome-launcher": "^2.0.0",
|
"karma-chrome-launcher": "^2.0.0",
|
||||||
"karma-cli": "^1.0.1",
|
"karma-cli": "^1.0.1",
|
||||||
|
"karma-coverage-istanbul-reporter": "^1.3.0",
|
||||||
"karma-jasmine": "^1.0.2",
|
"karma-jasmine": "^1.0.2",
|
||||||
"karma-remap-istanbul": "0.4.0",
|
"karma-remap-istanbul": "0.4.0",
|
||||||
"karma-sauce-launcher": "1.1.0",
|
"karma-sauce-launcher": "1.1.0",
|
||||||
@@ -94,9 +95,9 @@
|
|||||||
"lodash": "4.17.4",
|
"lodash": "4.17.4",
|
||||||
"markdown-loader": "^0.1.7",
|
"markdown-loader": "^0.1.7",
|
||||||
"marked": "0.3.6",
|
"marked": "0.3.6",
|
||||||
"ngx-bootstrap": "1.6.6",
|
|
||||||
"ng2-page-scroll": "4.0.0-beta.2",
|
"ng2-page-scroll": "4.0.0-beta.2",
|
||||||
"ngm-cli": "0.4.0",
|
"ngm-cli": "0.4.0",
|
||||||
|
"ngx-bootstrap": "1.6.6",
|
||||||
"npm-run-all": "^4.0.1",
|
"npm-run-all": "^4.0.1",
|
||||||
"pre-commit": "1.2.2",
|
"pre-commit": "1.2.2",
|
||||||
"protractor": "5.0.0",
|
"protractor": "5.0.0",
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
import { Directive, EventEmitter, ElementRef, HostListener, Input, Output } from '@angular/core';
|
import { Directive, EventEmitter, ElementRef, HostListener, Input, Output } from '@angular/core';
|
||||||
|
|
||||||
import { FileUploader } from './file-uploader.class';
|
import { FileUploader, FileUploaderOptions } from './file-uploader.class';
|
||||||
|
|
||||||
@Directive({selector: '[ng2FileDrop]'})
|
@Directive({ selector: '[ng2FileDrop]' })
|
||||||
export class FileDropDirective {
|
export class FileDropDirective {
|
||||||
@Input() public uploader:FileUploader;
|
@Input() public uploader: FileUploader;
|
||||||
@Output() public fileOver:EventEmitter<any> = new EventEmitter();
|
@Output() public fileOver: EventEmitter<any> = new EventEmitter();
|
||||||
@Output() public onFileDrop:EventEmitter<File[]> = new EventEmitter<File[]>();
|
@Output() public onFileDrop: EventEmitter<File[]> = new EventEmitter<File[]>();
|
||||||
|
|
||||||
protected element:ElementRef;
|
protected element: ElementRef;
|
||||||
|
|
||||||
public constructor(element:ElementRef) {
|
public constructor(element: ElementRef) {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getOptions():any {
|
public getOptions(): FileUploaderOptions {
|
||||||
return this.uploader.options;
|
return this.uploader.options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getFilters():any {
|
public getFilters(): any {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('drop', ['$event'])
|
@HostListener('drop', [ '$event' ])
|
||||||
public onDrop(event:any):void {
|
public onDrop(event: any): void {
|
||||||
let transfer = this._getTransfer(event);
|
let transfer = this._getTransfer(event);
|
||||||
if (!transfer) {
|
if (!transfer) {
|
||||||
return;
|
return;
|
||||||
@@ -37,8 +37,8 @@ export class FileDropDirective {
|
|||||||
this.onFileDrop.emit(transfer.files);
|
this.onFileDrop.emit(transfer.files);
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('dragover', ['$event'])
|
@HostListener('dragover', [ '$event' ])
|
||||||
public onDragOver(event:any):void {
|
public onDragOver(event: any): void {
|
||||||
let transfer = this._getTransfer(event);
|
let transfer = this._getTransfer(event);
|
||||||
if (!this._haveFiles(transfer.types)) {
|
if (!this._haveFiles(transfer.types)) {
|
||||||
return;
|
return;
|
||||||
@@ -49,10 +49,10 @@ export class FileDropDirective {
|
|||||||
this.fileOver.emit(true);
|
this.fileOver.emit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('dragleave', ['$event'])
|
@HostListener('dragleave', [ '$event' ])
|
||||||
public onDragLeave(event:any):any {
|
public onDragLeave(event: any): any {
|
||||||
if ((this as any).element) {
|
if ((this as any).element) {
|
||||||
if (event.currentTarget === (this as any).element[0]) {
|
if (event.currentTarget === (this as any).element[ 0 ]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,16 +61,16 @@ export class FileDropDirective {
|
|||||||
this.fileOver.emit(false);
|
this.fileOver.emit(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _getTransfer(event:any):any {
|
protected _getTransfer(event: any): any {
|
||||||
return event.dataTransfer ? event.dataTransfer : event.originalEvent.dataTransfer; // jQuery fix;
|
return event.dataTransfer ? event.dataTransfer : event.originalEvent.dataTransfer; // jQuery fix;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _preventAndStop(event:any):any {
|
protected _preventAndStop(event: any): any {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _haveFiles(types:any):any {
|
protected _haveFiles(types: any): any {
|
||||||
if (!types) {
|
if (!types) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -83,13 +83,4 @@ export class FileDropDirective {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
_addOverClass(item:any):any {
|
|
||||||
item.addOverClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
_removeOverClass(item:any):any {
|
|
||||||
item.removeOverClass();
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,31 +4,31 @@ import { FileUploader } from './file-uploader.class';
|
|||||||
|
|
||||||
// todo: filters
|
// todo: filters
|
||||||
|
|
||||||
@Directive({selector: '[ng2FileSelect]'})
|
@Directive({ selector: '[ng2FileSelect]' })
|
||||||
export class FileSelectDirective {
|
export class FileSelectDirective {
|
||||||
@Input() public uploader:FileUploader;
|
@Input() public uploader: FileUploader;
|
||||||
@Output() public onFileSelected:EventEmitter<File[]> = new EventEmitter<File[]>();
|
@Output() public onFileSelected:EventEmitter<File[]> = new EventEmitter<File[]>();
|
||||||
|
|
||||||
protected element:ElementRef;
|
protected element: ElementRef;
|
||||||
|
|
||||||
public constructor(element:ElementRef) {
|
public constructor(element: ElementRef) {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getOptions():any {
|
public getOptions(): any {
|
||||||
return this.uploader.options;
|
return this.uploader.options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getFilters():any {
|
public getFilters(): any {
|
||||||
return void 0;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
public isEmptyAfterSelection():boolean {
|
public isEmptyAfterSelection(): boolean {
|
||||||
return !!this.element.nativeElement.attributes.multiple;
|
return !!this.element.nativeElement.attributes.multiple;
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('change', ['$event'])
|
@HostListener('change', ['$event'])
|
||||||
public onChange():any {
|
public onChange(): any {
|
||||||
// let files = this.uploader.isHTML5 ? this.element.nativeElement[0].files : this.element.nativeElement[0];
|
// let files = this.uploader.isHTML5 ? this.element.nativeElement[0].files : this.element.nativeElement[0];
|
||||||
let files = this.element.nativeElement.files;
|
let files = this.element.nativeElement.files;
|
||||||
let options = this.getOptions();
|
let options = this.getOptions();
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { EventEmitter } from '@angular/core';
|
||||||
import { FileLikeObject } from './file-like-object.class';
|
import { FileLikeObject } from './file-like-object.class';
|
||||||
import { FileItem } from './file-item.class';
|
import { FileItem } from './file-item.class';
|
||||||
import { FileType } from './file-type.class';
|
import { FileType } from './file-type.class';
|
||||||
@@ -32,6 +33,8 @@ export interface FileUploaderOptions {
|
|||||||
itemAlias?: string;
|
itemAlias?: string;
|
||||||
authTokenHeader?: string;
|
authTokenHeader?: string;
|
||||||
additionalParameter?:{[key: string]: any};
|
additionalParameter?:{[key: string]: any};
|
||||||
|
formatDataFunction?:Function;
|
||||||
|
formatDataFunctionIsAsync?:boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FileUploader {
|
export class FileUploader {
|
||||||
@@ -43,19 +46,23 @@ export class FileUploader {
|
|||||||
public _nextIndex:number = 0;
|
public _nextIndex:number = 0;
|
||||||
public autoUpload:any;
|
public autoUpload:any;
|
||||||
public authTokenHeader: string;
|
public authTokenHeader: string;
|
||||||
|
public response: EventEmitter<any>;
|
||||||
|
|
||||||
public options:FileUploaderOptions = {
|
public options:FileUploaderOptions = {
|
||||||
autoUpload: false,
|
autoUpload: false,
|
||||||
isHTML5: true,
|
isHTML5: true,
|
||||||
filters: [],
|
filters: [],
|
||||||
removeAfterUpload: false,
|
removeAfterUpload: false,
|
||||||
disableMultipart: false
|
disableMultipart: false,
|
||||||
|
formatDataFunction: function (item:FileItem) { return item._file; },
|
||||||
|
formatDataFunctionIsAsync: false
|
||||||
};
|
};
|
||||||
|
|
||||||
protected _failFilterIndex:number;
|
protected _failFilterIndex:number;
|
||||||
|
|
||||||
public constructor(options:FileUploaderOptions) {
|
public constructor(options:FileUploaderOptions) {
|
||||||
this.setOptions(options);
|
this.setOptions(options);
|
||||||
|
this.response = new EventEmitter<any>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public setOptions(options:FileUploaderOptions):void {
|
public setOptions(options:FileUploaderOptions):void {
|
||||||
@@ -291,6 +298,7 @@ export class FileUploader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected _xhrTransport(item:FileItem):any {
|
protected _xhrTransport(item:FileItem):any {
|
||||||
|
let that = this;
|
||||||
let xhr = item._xhr = new XMLHttpRequest();
|
let xhr = item._xhr = new XMLHttpRequest();
|
||||||
let sendable:any;
|
let sendable:any;
|
||||||
this._onBeforeUploadItem(item);
|
this._onBeforeUploadItem(item);
|
||||||
@@ -315,7 +323,7 @@ export class FileUploader {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sendable = item._file;
|
sendable = this.options.formatDataFunction(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
xhr.upload.onprogress = (event:any) => {
|
xhr.upload.onprogress = (event:any) => {
|
||||||
@@ -357,7 +365,18 @@ export class FileUploader {
|
|||||||
if (this.authToken) {
|
if (this.authToken) {
|
||||||
xhr.setRequestHeader(this.authTokenHeader, this.authToken);
|
xhr.setRequestHeader(this.authTokenHeader, this.authToken);
|
||||||
}
|
}
|
||||||
xhr.send(sendable);
|
xhr.onreadystatechange = function() {
|
||||||
|
if (xhr.readyState == XMLHttpRequest.DONE) {
|
||||||
|
that.response.emit(xhr.responseText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.options.formatDataFunctionIsAsync) {
|
||||||
|
sendable.then(
|
||||||
|
(result:any) => xhr.send(JSON.stringify(result))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
xhr.send(sendable);
|
||||||
|
}
|
||||||
this._render();
|
this._render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,147 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, DebugElement } from '@angular/core';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
import { inject, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { inject, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { FileUploader } from '../file-upload/file-uploader.class';
|
import { FileUploader } from '../file-upload/file-uploader.class';
|
||||||
import { FileUploadModule } from '../file-upload/file-upload.module';
|
import { FileUploadModule } from '../file-upload/file-upload.module';
|
||||||
|
import { FileDropDirective } from '../file-upload/file-drop.directive';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'container',
|
selector: 'container',
|
||||||
template: `<input type="file" ng2FileSelect [uploader]="uploader" />`
|
template: `<div type="file"
|
||||||
|
ng2FileDrop
|
||||||
|
[uploader]="uploader"
|
||||||
|
></div>`
|
||||||
})
|
})
|
||||||
export class ContainerComponent {
|
export class ContainerComponent {
|
||||||
public uploader:FileUploader = new FileUploader({url: 'localhost:3000'});
|
public get url(): string { return 'localhost:3000'; }
|
||||||
|
public uploader: FileUploader = new FileUploader({ url: this.url });
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Directive: FileSelectDirective', () => {
|
describe('Directive: FileDropDirective', () => {
|
||||||
|
|
||||||
|
let fixture: ComponentFixture<ContainerComponent>;
|
||||||
|
let hostComponent: ContainerComponent;
|
||||||
|
let directiveElement: DebugElement;
|
||||||
|
let fileDropDirective: FileDropDirective;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [FileUploadModule],
|
imports: [ FileUploadModule ],
|
||||||
declarations: [ContainerComponent],
|
declarations: [ ContainerComponent ],
|
||||||
providers: [ContainerComponent]
|
providers: [ ContainerComponent ]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be fine', inject([ContainerComponent], (fixture:ComponentFixture<ContainerComponent>) => {
|
beforeEach(() => {
|
||||||
expect(fixture).not.toBeNull();
|
fixture = TestBed.createComponent(ContainerComponent);
|
||||||
}));
|
hostComponent = fixture.componentInstance;
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
directiveElement = fixture.debugElement.query(By.directive(FileDropDirective));
|
||||||
|
fileDropDirective = directiveElement.injector.get(FileDropDirective) as FileDropDirective;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can be initialized', () => {
|
||||||
|
expect(fixture).toBeDefined();
|
||||||
|
expect(hostComponent).toBeDefined();
|
||||||
|
expect(fileDropDirective).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can set file uploader', () => {
|
||||||
|
expect(fileDropDirective.uploader).toBe(hostComponent.uploader);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get uploader options', () => {
|
||||||
|
const options = fileDropDirective.getOptions();
|
||||||
|
|
||||||
|
// Check url set through binding
|
||||||
|
expect(options.url).toBe(hostComponent.url);
|
||||||
|
|
||||||
|
// Check default options
|
||||||
|
expect(options.autoUpload).toBeFalsy();
|
||||||
|
expect(options.isHTML5).toBeTruthy();
|
||||||
|
expect(options.removeAfterUpload).toBeFalsy();
|
||||||
|
expect(options.disableMultipart).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get filters', () => {
|
||||||
|
const filters = fileDropDirective.getFilters();
|
||||||
|
|
||||||
|
// TODO: Update test once implemented
|
||||||
|
expect(filters).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles drop event', () => {
|
||||||
|
spyOn(fileDropDirective, 'onDrop');
|
||||||
|
|
||||||
|
directiveElement.triggerEventHandler('drop', getFakeEventData());
|
||||||
|
|
||||||
|
expect(fileDropDirective.onDrop).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds file to upload', () => {
|
||||||
|
spyOn(fileDropDirective.uploader, 'addToQueue');
|
||||||
|
|
||||||
|
let fileOverData;
|
||||||
|
fileDropDirective.fileOver.subscribe((data: any) => fileOverData = data);
|
||||||
|
|
||||||
|
let fileDropData;
|
||||||
|
fileDropDirective.onFileDrop.subscribe((data: File[]) => fileDropData = data);
|
||||||
|
|
||||||
|
fileDropDirective.onDrop(getFakeEventData());
|
||||||
|
|
||||||
|
const uploadedFiles = getFakeEventData().dataTransfer.files;
|
||||||
|
const expectedArguments = [ uploadedFiles, fileDropDirective.getOptions(), fileDropDirective.getFilters() ];
|
||||||
|
|
||||||
|
expect(fileDropDirective.uploader.addToQueue).toHaveBeenCalledWith(...expectedArguments);
|
||||||
|
expect(fileOverData).toBeFalsy();
|
||||||
|
expect(fileDropData).toEqual(uploadedFiles);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles dragover event', () => {
|
||||||
|
spyOn(fileDropDirective, 'onDragOver');
|
||||||
|
|
||||||
|
directiveElement.triggerEventHandler('dragover', getFakeEventData());
|
||||||
|
|
||||||
|
expect(fileDropDirective.onDragOver).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles file over', () => {
|
||||||
|
let fileOverData;
|
||||||
|
fileDropDirective.fileOver.subscribe((data: any) => fileOverData = data);
|
||||||
|
|
||||||
|
fileDropDirective.onDragOver(getFakeEventData());
|
||||||
|
|
||||||
|
expect(fileOverData).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles dragleave event', () => {
|
||||||
|
spyOn(fileDropDirective, 'onDragLeave');
|
||||||
|
|
||||||
|
directiveElement.triggerEventHandler('dragleave', getFakeEventData());
|
||||||
|
|
||||||
|
expect(fileDropDirective.onDragLeave).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles file over leave', () => {
|
||||||
|
let fileOverData;
|
||||||
|
fileDropDirective.fileOver.subscribe((data: any) => fileOverData = data);
|
||||||
|
|
||||||
|
fileDropDirective.onDragLeave(getFakeEventData());
|
||||||
|
|
||||||
|
expect(fileOverData).toBeFalsy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getFakeEventData(): any {
|
||||||
|
return {
|
||||||
|
dataTransfer: {
|
||||||
|
files: [ 'foo.bar' ],
|
||||||
|
types: [ 'Files' ]
|
||||||
|
},
|
||||||
|
preventDefault: () => undefined,
|
||||||
|
stopPropagation: () => undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
99
src/spec/file-select.directive.spec.ts
Normal file
99
src/spec/file-select.directive.spec.ts
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||||
|
import { Component, DebugElement } from '@angular/core';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import { FileUploadModule } from '../file-upload/file-upload.module';
|
||||||
|
import { FileSelectDirective } from '../file-upload/file-select.directive';
|
||||||
|
import { FileUploader } from '../file-upload/file-uploader.class';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'container',
|
||||||
|
template: `<input type="file"
|
||||||
|
ng2FileSelect
|
||||||
|
[uploader]="uploader"
|
||||||
|
/>`
|
||||||
|
})
|
||||||
|
export class ContainerComponent {
|
||||||
|
public get url(): string { return 'localhost:3000'; }
|
||||||
|
public uploader: FileUploader = new FileUploader({ url: this.url });
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Directive: FileSelectDirective', () => {
|
||||||
|
let fixture: ComponentFixture<ContainerComponent>;
|
||||||
|
let hostComponent: ContainerComponent;
|
||||||
|
let directiveElement: DebugElement;
|
||||||
|
let fileSelectDirective: FileSelectDirective;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [ FileUploadModule ],
|
||||||
|
declarations: [ ContainerComponent ],
|
||||||
|
providers: [ ContainerComponent ]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ContainerComponent);
|
||||||
|
hostComponent = fixture.componentInstance;
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
directiveElement = fixture.debugElement.query(By.directive(FileSelectDirective));
|
||||||
|
fileSelectDirective = directiveElement.injector.get(FileSelectDirective) as FileSelectDirective;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can be initialized', () => {
|
||||||
|
expect(fixture).toBeDefined();
|
||||||
|
expect(hostComponent).toBeDefined();
|
||||||
|
expect(fileSelectDirective).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can set file uploader', () => {
|
||||||
|
expect(fileSelectDirective.uploader).toBe(hostComponent.uploader);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get uploader options', () => {
|
||||||
|
const options = fileSelectDirective.getOptions();
|
||||||
|
|
||||||
|
// Check url set through binding
|
||||||
|
expect(options.url).toBe(hostComponent.url);
|
||||||
|
|
||||||
|
// Check default options
|
||||||
|
expect(options.autoUpload).toBeFalsy();
|
||||||
|
expect(options.isHTML5).toBeTruthy();
|
||||||
|
expect(options.removeAfterUpload).toBeFalsy();
|
||||||
|
expect(options.disableMultipart).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get filters', () => {
|
||||||
|
const filters = fileSelectDirective.getFilters();
|
||||||
|
|
||||||
|
// TODO: Update test once implemented
|
||||||
|
expect(filters).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can check if element is empty', () => {
|
||||||
|
const isElementEmpty = fileSelectDirective.isEmptyAfterSelection();
|
||||||
|
|
||||||
|
expect(isElementEmpty).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can listed on change event', () => {
|
||||||
|
spyOn(fileSelectDirective, 'onChange');
|
||||||
|
|
||||||
|
directiveElement.triggerEventHandler('change', {});
|
||||||
|
|
||||||
|
expect(fileSelectDirective.onChange).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles change event', () => {
|
||||||
|
spyOn(fileSelectDirective.uploader, 'addToQueue');
|
||||||
|
|
||||||
|
fileSelectDirective.onChange();
|
||||||
|
|
||||||
|
const expectedArguments = [ directiveElement.nativeElement.files,
|
||||||
|
fileSelectDirective.getOptions(),
|
||||||
|
fileSelectDirective.getFilters() ];
|
||||||
|
expect(fileSelectDirective.uploader.addToQueue).toHaveBeenCalledWith(...expectedArguments);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user