The original Droplet module was created by me for Ember.js – ngDroplet
is the Angular.js version. ngDroplet
allows you to easily support drag and drop uploading in Angular.js – with additional sugar for uploading and managing files.
- Heroku: http://ng-droplet.herokuapp.com/
- Bower:
bower install ng-droplet
ngDroplet
provides a useful interface with a handful of methods to interact with the module. However, to begin supporting the drag and drop feature, you don't need anything special – simply add the droplet
node (or droplet
attribute) to the DOM:
<!-- As an element -->
<droplet></droplet>
<!-- As an attribute -->
<section data-droplet></section>
By adding the droplet
node — or of course, attribute — your application will automatically support the dragging and dropping of files. However, in order to make the module useful, you should hook into the directive's interface – by using the ng-model
attribute on the droplet
node:
<droplet ng-model="interface"></droplet>
In the above case, the interface
references a variable in your current scope. Once ngDroplet
has successfully bootstrapped itself, you can begin interacting with the module through its interface. Before you begin invoking methods on the interface, you must first listen for ngDroplet
to broadcast the $dropletReady
event:
$scope.$on('$dropletReady', function whenDropletReady() {
// Directive's interface is ready to be used...
});
With the directive's interface there are many methods you can invoke. Initially you'll want to define which extensions are permitted to be uploaded by the module – you can do achieve this via the allowedExtensions
method:
$scope.$on('$dropletReady', function whenDropletReady() {
$scope.interface.allowedExtensions(['png', 'jpg', 'bmp', 'gif']);
});
...Or support every extension with:
$scope.interface.allowedExtensions([/.+/]);
Finally you'll need to add a button to initiate the upload process:
<input type="button" value="Upload Files" ng-click="interface.uploadFiles()"/>
Voila!
With all the files that the user drops onto the DOM, you'll most likely wish to display them – even showing a preview of any images they have added.
It's necessary to know that each file has a special type assigned to it, and you will need to know these types when iterating over the files – all of the possible types are added to the directive's interface as the FILE_TYPES
constant:
$scope.FILE_TYPES = { VALID: 1, INVALID: 2, DELETED: 4, UPLOADED: 8 };
Note: ngDroplet
also defines a FILE_TYPES.ALL
property.
Therefore to iterate over only the valid files that are permitted to be uploaded, you must use the FILE_TYPES.VALID
constant when invoking the getFiles
methods on the interface:
<div ng-repeat="model in interface.getFiles(interface.FILE_TYPES.VALID)">
{{model.file.name}}
</div>
As the interface.FILE_TYPES
are bitwise values, you can combine them to fetch more than one type at a time — in the following case interface.FILE_TYPES.VALID
and interface.FILE_TYPES.INVALID
:
interface.getFiles(interface.FILE_TYPES.VALID | interface.FILE_TYPES.INVALID)
It's also worth noting that if you emit any type when invoking getFiles
then the method will return all of the files.
Before you begin iterating of the files it is perhaps necessary to know about the DropletModel
which is assigned to each and every file added to ngDroplet
– the DropletModel
model is initiated using the load
method:
load: function load(file) {
this.file = file;
this.date = new $window.Date();
this.mimeType = file.type;
this.extension = $scope.getExtension(file);
}
Each DropletModel
is then assigned a type:
setType: function setType(type) {
this.type = type;
}
// ...
model.setType($scope.FILE_TYPES.VALID);
Where the parameter — type
— relates to the aforementioned FILE_TYPES
constant. DropletModel
also contains a handful of useful methods:
deleteFile
: Assign the file theFILE_TYPES.DELETED
value;isImage
: Determines if the file is a valid image;setType
: Sets the type ($scope.FILE_TYPES
) of the file;
ngDroplet
also supports the previewing of valid images to the user prior to the files being uploaded – before attempting to preview a file you should first determine if it's a valid image using the isImage
method on the DropletModel
:
<div ng-repeat="model in interface.getFiles(interface.FILE_TYPES.VALID)">
<droplet-preview ng-model="model" ng-show="model.isImage()"></droplet-preview>
<section class="filename" ng-show="!model.isImage()">{{model.file.name}}</section>
</div>
It's also worth noting that the droplet-preview
directive is also supported in attribute form: <section data-droplet-preview></section>
.
Essentially the droplet-preview
node accepts any File
object as its ng-model
– but it will load only those files that pass the isImage()
method's validation.
Due to the directive's interface you can attach an input
element that will allow users to add files in the traditional way – ngDroplet
also supports input
elements with the multiple
attribute. All you need to do is attach the interface
variable to the ng-model
attribute:
<!-- Single -->
<droplet-upload-single ng-model="interface"></droplet-upload-single>
<!-- Multiple -->
<droplet-upload-multiple ng-model="interface"></droplet-upload-multiple>
ngDroplet
uses the X-File-Size
header to calculate the progress of the uploading – all of the information is periodically updated to the interface.progress
object in the following format:
$scope.requestProgress = { percent: 0, total: 0, loaded: 0 };
With the above object you can merely print it to the screen like so: {{interface.progress.percent}}%
– or dream up imaginative ways to use this useful information.
uploadFiles
: Responsible for initiating the uploading process;progress
: Contains an object referring to the upload progress;isUploading
: Determines if we're currently uploading;isError
: Determines if there is an error;isReady
: Determines if there are files ready to be uploaded;addFile
: Adds a file to the list – must be aFile
object;traverseFiles
: Accepts aFileList
object for adding many files;disableXFileSize
: Disables adding theX-File-Size
header;useArray
: Whether to use file of file[] as the POST name;setRequestUrl
: Defines the URL to issue the POST request to;setRequestHeaders
: Set additional request headers;setPostData
: Set additional POST data;getFiles
: Iterates over the files of any given bitwise type(s);allowedExtensions
: Specifies the extensions permitted to be uploaded;defineHTTPSuccess
: List of HTTP status codes that denote success;useParser
: Configure a custom function for parsing the responses;maximumValidFiles
: Defines how many valid files are permitted at once;
By default ngDroplet
will attempt to parse the response as JSON, however if you want to use a custom function then you can set it using the interface.options.useParser
method:
interface.useParser(function myCustomerParserFn(responseText) {
return responseText.toLowerCase();
});
HTTP status codes can also be defined using regular expressions – all that you need to do is pass in RegExp
objects in the array of status codes.
For example to assert that every 2**
HTTP status code is valid, you can specify it like so:
interface.defineHTTPSuccess([/2.{2}/]);
You are also allowed to mix and match RegExp
objects with Number
objects:
interface.defineHTTPSuccess([/2.{2}/, 301, 302]);
$dropletReady
: Emitted when the interface has been binded;$dropletSuccess
: Emitted when files have been uploaded;$dropletError
: Emitted when an error has occurred;$dropletFileAdded
: Emitted when a file has been added;$dropletFileDeleted
: Emitted when a file has been deleted;