Plupload is a very configurable JavaScript library you can use to allow your users to upload images. I’ve already used it in a few projects. I now wanted to use it in my current AngularJS project. Integrating Plupload in an AngularJS project is not especially difficult. There are already a few articles showing how this can be done. But it gets more difficult, when you try to integrate it into a dialog.
When initialized, Plupload puts an overlay above the browse button. This unfortunately only works if this element is displayed. If it is not displayed, the Plupload initialization will fail.
When working with dialogs, this means you need to execute the initialization of Plupload once the dialog is already displayed.
Let’s assume you have the use the following method to open a dialog using ngDialog:
$scope.uploadFile = function(){
ngDialog.open({
template: '/template/fileUploadDialog.html',
controller: 'FileUploadController'
});
};
and your controller looks like this:
app.controller('FileUploadController', function($scope){
$scope.uploader = new plupload.Uploader({
browse_button: 'browse',
url: 'upload.php'
});
$scope.uploader.init();
});
Or if you are using angular-dialog-service:
$scope.uploadFile = function () {
dialogs.create('/template/fileUploadDialog.html', 'FileUploadController', {}, {
'backdrop': false,
'size': 'sm',
'copy': false,
'windowClass': 'dialog-type-primary'
});
};
and the same controller.
You will see that although you do not get any kind of error, nothing will happen when you click on the browse button. This is because no overlay was added by Plupload. If you put a breakpoint in the controller code, you will see that the dialog is not yet displayed when the code runs.
This is because Plupload has issues rendering inside elements which are hidden at initialization time You need to “refresh” Plupload after the dialog has been displayed:
$scope.uploader.refresh();
Now we know the root cause of the problem, all we need to do is either call the refresh method after displaying the dialog or just initialize Plupload after displaying the dialog. The problem is that I never found out how to provide a callback to get triggered after the dialog has been displayed.
After googling for it with no result, I decided to do it with a hack (won’t win a design price with this one but it works). Assuming the dialog will never take more than 300 milliseconds to display and the user will need at least 300 milliseconds to find the browse button, you can just solve it by executing some code asynchronously using setTimeout or $timeout (since we work with AngularJS):
app.controller('FileUploadController', function($scope, $timeout){
$scope.uploader = new plupload.Uploader({
browse_button: 'browse',
url: 'upload.php'
});
$timeout(function () {
$scope.uploader.init();
}, 300);
});
Now your browse button should be working.
I like your code its simple and effective.