Master Branch
Develop Branch
An Angular module for simple desktop file drag and drop with automatic file validation and dynamic style adjustment.
Currently built against Angular ^5.2.3 and Typescript ^2.6.2
ng2-file-drop has the following additional dependancies
- TsLerp: Typescript library for lerping single and multi-sample data sets over time
- Add the package to your 'dependencies' list in
package.json
and runnpm install
"ng2-file-drop": "^5.0.0"
Optionally, you can manually install the package using the npm command line
npm install ng2-file-drop --save
- Add ng2-file-drop to both your
map
andpackages
structures insystemjs.config.js
var map = {
...
'tslerp': 'node_modules/tslerp',
'ng2-file-drop': 'node_modules/ng2-file-drop'
};
var packages = {
...
'tslerp': { main: 'index.js', defaultExtension: 'js' },
'ng2-file-drop': { main: 'index.js', defaultExtension: 'js' },
};
- Optionally, add the
rootDir
option totsconfig.json
to make sure TypeScript's default root path algorithm doesn't pull in thenode_modules
folder
All the examples shown below are taken from the samples application.
Check out the repository, browse to the './samples' folder and run npm install
to install all the required dependancies.
Note: Running npm install
on the sample project requires that Python 2.7.x is available on the command line as it runs a couple of Python scripts to correctly set up the npm_modules folder.
ng2-file-drop is developed in Visual Studio Code so once npm install
has finished you should be able to open the './samples' folder in VS Code and it will run out of the box (by default it uses lite-server which is installed as part of npm install
).
If you are not using Visual Studio Code, browse to the './samples' folder and run tsc
to build the application. Then open your local server of choice pointing to ./samples as the root directory.
To use ng2-file-drop, you need to import the Ng2FileDropModule into the relevent module in your application. In the sample application this is done in the entry module - app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { Ng2FileDropModule } from 'ng2-file-drop';
@NgModule({
imports: [
BrowserModule,
Ng2FileDropModule,
],
bootstrap: [
AppComponent,
],
})
export class AppModule { }
Enabling File Drag on an element is remarkably simple and can see seen in image-validation.
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'my-custom-component',
// Simply add the 'ng2FileDrop' selector to the target div
template: `<div ng2FileDrop class="custom-component-drop-zone"></div>`
// Define the size of the file drop zone
styles: [`
.custom-component-drop-zone {
width: 300px;
height: 300px;
}
`]
})
export class MyCustomComponent {
}
If you want to enable dropping multiple files are once, when defining ng2FileDrop, define ng2FileDropAcceptMultiple as an input parameter
<div ng2FileDrop ... [ng2FileDropAcceptMultiple]="true"></div>
You can specify a set of callbacks that will trigger when a drag event happens, which can be seen in size-validation.
The available callbacks are
- When one or more files are initially dragged into the target space
- When one or more files are dragged out of the target space
- When a file is dropped and it is accepted by 'ng2-file-drop' (when ng2FileDropAcceptMultiple = false)
- When a file is dropped and it is rejected by 'ng2-file-drop' (when ng2FileDropAcceptMultiple = false)
- When one or more files are dropped (when ng2FileDropAcceptMultiple = true)
import { Component } from '@angular/core';
import { Ng2FileDropAcceptedFile, Ng2FileDropRejectedFile } from 'ng2-file-drop';
@Component({
moduleId: module.id,
selector: 'my-custom-component',
template: `<!-- my_custom.component.html -->
<!-- Specify the callbacks in 'MyCustomComponent' for each event -->
<div ng2FileDrop class="custom-component-drop-zone"
(ng2FileDropHoverStart)="dragFileOverStart()" (ng2FileDropHoverEnd)="dragFileOverEnd()"
(ng2FileDropFileAccepted)="dragFileAccepted($event)" (ng2FileDropFileRejected)="dragFileRejected($event)"
</div>
<div ng2FileDrop class="custom-component-drop-zone"
[ng2FileDropAcceptMultiple]="true"
(ng2FileDropHoverStart)="dragFileOverStart()" (ng2FileDropHoverEnd)="dragFileOverEnd()"
(ng2FileDropFilesDropped)="dragFilesDropped($event)"
</div>`,
styles: [`
.custom-component-drop-zone {
width: 300px;
height: 300px;
}
`]
})
export class MyCustomComponent {
// File being dragged has moved into the drop region
private dragFileOverStart() {
}
// File being dragged has moved out of the drop region
private dragFileOverEnd() {
}
// File being dragged has been dropped and is valid
private dragFileAccepted(acceptedFile: Ng2FileDropAcceptedFile) {
}
// File being dragged has been dropped and has been rejected
private dragFileRejected(rejectedFile: Ng2FileDropRejectedFile) {
}
// Files being dragged have been dropped.
private dragFilesDropped(droppedFile: Ng2FileDropFilesDropped) {
}
}
Regardless of whether a file is accepted or rejected, you will be provided with a File object via either Ng2FileDropRejectedFile.file or Ng2FileDropAcceptedFile.file, which can be used to load, display, upload or otherwise interact with.
This can be seen in image-validation.component.ts which takes the dropped files and displays it in the browser.
import { Component } from '@angular/core';
import { Ng2FileDropAcceptedFile } from 'ng2-file-drop';
@Component({
...
})
export class ImageValidationComponent {
...
// Takes the dropped image and displays it in the image tag
private dragFileAccepted(acceptedFile: Ng2FileDropAcceptedFile) {
// Load the image in
let fileReader = new FileReader();
fileReader.onload = () => {
// Set and show the image
this.currentProfileImage = fileReader.result;
this.imageShown = true;
};
// Read in the file
fileReader.readAsDataURL(acceptedFile.file);
}
}
When a file is rejected you can identify the reason for it being rejected in Ng2FileDropRejectedFile.rejectionReason which can take one of the following values
- Ng2FileDropRejections.None
- Ng2FileDropRejections.FileType
- Ng2FileDropRejections.FileSize
- Ng2FileDropRejections.Unknown
import { Component } from '@angular/core';
import { Ng2FileDropRejectedFile, Ng2FileDropRejections } from 'ng2-file-drop';
@Component({
...
})
export class ImageValidationComponent {
...
// Takes the dropped image and displays it in the image tag
private dragFileRejected(rejectedFile: Ng2FileDropRejectedFile) {
// Respond to the reason for rejection
if (rejectedFilerejectionReason === Ng2FileDropRejections.FileType) {
} else if (rejectedFilerejectionReason === Ng2FileDropRejections.FileSize) {
} else {
}
}
}
When ng2FileDropAcceptMultiple is set to true the callbacks ng2FileDropFileAccepted and ng2FileDropFileRejected will not be emitted. Instead ng2FileDropFilesDropped will be emitted when one or many files are dropped.
import { Component } from '@angular/core';
import { Ng2FileDropFilesDropped } from 'ng2-file-drop';
@Component({
...
})
export class ImageValidationComponent {
...
// Takes the dropped image and displays it in the image tag
private dragFilesDropped(droppedFiles: Ng2FileDropFilesDropped) {
if (droppedFiles.accepted.length > 0) {
...
}
if (droppedFiles.rejected.length > 0) {
...
}
}
}
It is possible to define a set of criteria for the file to meet before it can be accepted, and if the file doesn't match those criteria it will be returned to the client as a 'Ng2FileDropRejectedFile'.
It is possible to define the following requirements
- File type (as seen in image-validation.component.ts)
- File size (as seen in size-validation.component.ts)
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'my-custom-component',
template: `<!-- my_custom.component.html -->
<!-- Set criteria for only image types under 1MB in size-->
<div ng2FileDrop class="custom-component-drop-zone"
[ng2FileDropSupportedFileTypes]="supportedFileTypes"
[ng2FileDropMaximumSizeBytes]="maximumFileSizeInBytes"
(ng2FileDropFileAccepted)="dragFileAccepted($event)"
</div>`
styles: [`
.custom-component-drop-zone {
width: 300px;
height: 300px;
}
`]
})
export class MyCustomComponent {
// Required criteria for all files (only image types under 1MB in size)
private supportedFileTypes: string[] = ['image/png', 'image/jpeg', 'image/gif'];
private maximumFileSizeInBytes: number = 1e+6;
// File being dragged has been dropped and is valid
private dragFileAccepted(acceptedFile: Ng2FileDropAcceptedFile) {
// Any files passed through here will have met the requested criteria
}
}
By default ng2-file-drop will automatically style the drop zone, highlighting it in blue when hovering, and flashing red when a file is rejected. You can disable this behaviour as done in disable-styles.
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'my-custom-component',
// Disable the default style of drop zones
template: `<div ng2FileDrop
class="custom-component-drop-zone
[ng2FileDropDisableStyles]="true"
</div>`
// Define the size of the file drop zone
styles: [`
.custom-component-drop-zone {
width: 300px;
height: 300px;
}
`]
})
export class MyCustomComponent {
}
- Added support for Angular 5 (built against 5.2.3)
- Increased to Version 4 to match the version of Angular this build supports
- Added peerDependancies to the npm package to support both npm2 and npm3
- Added support for dropping multiple files - #25
- Updated to Angular ^4.1.3 and Typescript ^2.3.2 - #26
- Altered used of moduleId for Webpack support - #27
- Documentation update
- Support for Angular versions 2.0.0 - 2.4.7
- Fixed - Safari Issue: Can't find variable: DragEvent - #4
- Updated package requirements to Typescript ^2.0.0 plus related package upgrades
- Updated Angular dependancy to 2.0.0
- Initial release