Skip to content

Commit

Permalink
Merge pull request #66 from r-hannuschka/development
Browse files Browse the repository at this point in the history
Version 2.0
  • Loading branch information
r-hannuschka authored Sep 8, 2019
2 parents a62430d + 846c566 commit 09569ad
Show file tree
Hide file tree
Showing 50 changed files with 10,480 additions and 7,312 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ orbs:
defaults: &defaults
working_directory: ~/ngx-fileupload
docker:
- image: circleci/node:10.16.0-browsers
- image: circleci/node:10.16.3-browsers

aliases:
- &filter_master
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/out-tsc
/src/coverage
/src/documentation
/server/upload.log
/src/server/upload.log

# Only exists if Bazel was run
/bazel-out
Expand Down
345 changes: 7 additions & 338 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,6 @@ Angular 8+ async fileupload with progressbar

___

## Contents

- [NgxFileupload](#NgxFileupload)
- [Contents](#Contents)
- [Installation](#Installation)
- [Usage](#Usage)
- [Examples](#Examples)
- [Custom Item Template](#Custom-Item-Template)
- [Full Customize](#Full-Customize)
- [Validators](#Validators)
- [Add Params / Headers to Upload](#Add-Params--Headers-to-Upload)
- [Development](#Development)
- [Tests](#Tests)
- [Credits](#Credits)
- [Author](#Author)
- [Other Modules](#Other-Modules)

## Installation

npm
Expand All @@ -38,330 +21,16 @@ npm i --save @r-hannuschka/ngx-fileupload angular-pipes

## Usage

app.module.ts

```js
import { NgModule, Injectable } from "@angular/core";
import { NgxFileUploadModule } from "@r-hannuschka/ngx-fileupload";

@NgModule({
imports: [
...
NgxFileUploadModule
],
exports: [...],
declarations: [...]
})
export class AppModule { }
```

app.component.html

```html
<ngx-fileupload [url]="<URL>"></ngx-fileupload>
```

Upload file directly in post body (no formdata)

```html
<!-- file will directly sends with POST and not added to FormData Object default is true-->
<ngx-fileupload [url]="<URL>" [useFormData]="false"></ngx-fileupload>
```

Upload file with form data but custom form data field

```html
<!-- file will uploaded via FormData with field name myFileUploadField, (default: 'file') -->
<ngx-fileupload [url]="<URL>" [formDataName]="'myFileUploadField'"></ngx-fileupload>
```

## Examples

### Custom Item Template

if a custom template will be added, it will receive UploadTemplateContext object which contains:

data:UploadData (current upload informations)

| name | type | description | values |
|---|---|---|---|
| hasError | boolean | flag upload got error | |
| isSuccess | boolean | upload was successfully |
| isValid | boolean | current upload is valid |
| message | string | current error / validation or success message|
| name | string | name of file | |
| progress | number | progress in percent | |
| state | string | current state of upload | canceled, queued, progress, error, uploaded, invalid|
| size | number | size of file | |
| uploaded | number | uploaded size in byte | |

```html
<ng-template #customItemTemplate let-uploadData="data" ...>
<h2>{{uploadData.name}}</h2>
<div>Progress: {{uplodaData.uploaded}}/{{uploadData.size}}
</ng-template>
```

ctrl:UploadControl (start/stop/retry an upload)

```html
<ng-template #customItemTemplate ... let-uploadCtrl="ctrl">
<!-- retry failed upload -->
<button type="button" *ngIf="data.hasError" (click)="uploadCtrl.retry()">retry</button>

<!-- start current upload -->
<button type="button" *ngIf="!data.hasError" (click)="uploadCtrl.start()">start</button>

<!-- cancel / remove current upload -->
<button type="button" (click)="uploadCtrl.cancel()">stop</button>
</ng-template>
```

simply define a *ng-template* tag and pass it to *ngx-fileupload* component

```html
<ng-template #customItemTemplate let-uploadData="data" let-uploadCtrl="ctrl">
...
</ng-template>

<ngx-fileupload [url]="<URL>" [itemTemplate]="customItemTemplate"></ngx-fileupload>
```

___

### Full Customize

my.component.ts

```ts
import { FileUpload, UploadModel, UploadState } from "@r-hannuschka/ngx-fileupload";

@Component({
selector: "my-component",
styleUrls: ["./my.component.scss"],
templateUrl: "my.component.html",
})
export class MyComponent {

/**
* all file uploades, which will be added to upload-item view
*/
public uploads: FileUpload[] = [];

/**
* new uploads added with drag and drop
*/
public onUploadsAdd( uploads: FileUpload[] ) {
this.uploads.push( ...uploads );
}

/**
* handle upload change event,
* if upload has been completed or canceled remove it from list
*/
public handleUploadChange( upload: UploadModel, fileUpload: FileUpload ) {
let completed = upload.state === UploadState.CANCELED;
completed = completed || upload.state === UploadState.UPLOADED;

if ( completed ) {
const idx = this.uploads.indexOf(fileUpload);
this.uploads.splice( idx, 1 );
}
}
}
```

my.component.html

```html
<!--
define custom item template, if we dont pass a template to
ngx-fileupload-item it will take default template as fallback
-->
<ng-template #itemTemplate let-uploadData="data" let-uploadCtrl="ctrl">

<div class="title">
{{uploadData.name}}
</div>

<div class="actions">
<button type="button"
*ngIf="!uploadData.hasError"
[disabled]="uploadData.invalid || uploadData.state !== 'queued'"
(click)="uploadCtrl.start()">
start
</button>
<button type="button" (click)="uploadCtrl.cancel()">
stop
</button>
</div>

</ng-template>

<!-- show all uploads -->
<div class="file-upload--list">
<ng-container *ngFor="let item of uploads">
<ngx-fileupload-item
[upload]="item"
[template]="itemTemplate"
(changed)="handleUploadChange($event, item)">
</ngx-fileupload-item>
</ng-container>
</div>

<!--
add directive ngxFileUpload to create new uploads if files get dropped here
or selected from file window.
optional pass useFormData: boolean (default: true)
optional pass formDataName: string (default file)
-->
<div class="fileupload dropzone"
[ngxFileUpload]="url"
[useFormData]="true"
[formDataName]="'myFileUpload'"
(add)="onUploadsAdd($event)"
#myNgxFileUploadRef="ngxFileUploadRef">

<span>
Drop Files or Click to add uploads.
</span>
</div>

<!-- button, on click use myNgxFileUploadRef to upload all files at once -->
<button class="btn btn-upload" type="button" (click)="myNgxFileUploadRef.uploadAll()">Upload</button>
<button class="btn btn-clear" type="button" (click)="myNgxFileUploadRef.cleanAll()">Clean Up</button>
<button class="btn btn-cancel" type="button" (click)="myNgxFileUploadRef.cancelAll()">Cancel</button>
```

___

### Validators

validators/max-size.validator.ts

```ts
import {
NgxFileUploadValidation,
ValidationResult
} from "@r-hannuschka/ngx-fileupload";

export class MaxUploadSizeValidator implements NgxFileUploadValidator {

/**
* validate max upload size to 1MB
*/
public validate(file: File): ValidationResult {
const valid = (file.size / (1024 * 1024)) < 1;
const error = !valid ? "Max file size 1MByte" : "";
return { valid, error };
}
}
<ngx-fileupload [url]="'http://localhost:3000/upload'"></ngx-fileupload>
```

app-upload.module.ts
To get more detailed informations please check out the docs

We create a own module for validation to keep main module clean, you can add as many validators you want if needed. If no Validators are passed all files will uploaded to server.

```ts
import { NgModule } from "@angular/core";
import {
NgxFileUploadModule,
NGX_FILEUPLOAD_VALIDATOR
} from "@r-hannuschka/ngx-fileupload";
import { MaxUploadSizeValidator } from "./validators/max-size.validator";

@NgModule({
exports: [ NgxFileUploadModule ],
imports: [ NgxFileUploadModule ],
providers: [{
provide: NGX_FILEUPLOAD_VALIDATOR,
useClass: MaxUploadSizeValidator,
multi: true
}, {
provide: NGX_FILEUPLOAD_VALIDATOR,
useClass: SomeOtherValidator,
multi: true
}],
})
export class AppUploadModule { }
```

app.module.ts

simply import AppUploadModule into main module

```ts
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { AppComponent } from "./app.component";
import { AppUploadModule } from "./app-upload.module";

@NgModule( {
declarations: [
AppComponent
],
imports: [
AppUploadModule,
BrowserModule
],
bootstrap: [AppComponent],
} )
export class AppModule { }
```

___

### Add Params / Headers to Upload

To add additional params / headers HTTP Interceptors should be used from angular to modify
request.

upload.interceptor.ts

```ts
import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent } from "@angular/common/http";
import { Observable } from "rxjs";

export class UploadInterceptor implements HttpInterceptor {

public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const needle = new RegExp("^/lib/upload");
if (req.url.match(needle) && req.body.has("file")) {
const fileName = req.body.get("file").name;
const request: HttpRequest<any> = req.clone({
/** add additional params */
setParams: {
"fileName": fileName,
}
});
return next.handle(request);
}
return next.handle(req);
}
}
```

app-upload.module.ts

```ts
import { NgModule } from "@angular/core";
import { HTTP_INTERCEPTORS } from "@angular/common/http";
import { NgxFileUploadModule } from "@r-hannuschka/ngx-fileupload";

@NgModule({
exports: [ NgxFileUploadModule ],
imports: [ NgxFileUploadModule ],
providers: [{
// ... validators
}, {
provide: HTTP_INTERCEPTORS,
useClass: UploadInterceptor,
multi: true
}],
})
export class AppUploadModule { }
```
- [Upload Component](./docs/upload-component.md)
- [Upload Directive](./docs/upload-directive.md)
- [Upload Item](./docs/upload-item.md)
- [Validation](./docs/validation.md)

___

Expand All @@ -385,7 +54,7 @@ npm start

```bash
# end to end tests
ng e2e
npm run e2e

# unit tests
ng test ngx-fileupload
Expand Down
Loading

0 comments on commit 09569ad

Please sign in to comment.