0

we have written a directive in angular, which uses blueimp-fileupload. As long as we do not use the requireJs optimizer the code works fine. But after we run requireJs optimizer, we get the following error:

Error: cannot call methods on fileupload prior to initialization; attempted to call method 'destroy'

After requireJs the Stack of the deletion after the state change is different.

Wihtout RequireJs it only calls this function once:

  jQuery.cleanData = function(elems) {
      var events;
      for (var i = 0, elem; (elem = elems[i]) != null; i++) {
        events = jQuery._data(elem, "events");
        if (events && events.$destroy) {
          jQuery(elem).triggerHandler('$destroy');
        }
      }
      originalCleanData(elems);
    };

But after RequireJs optimizer it calls the function cleanData 3 times (but different implementations, once in the jquery.js, jquery-ui.js and jquery-ui-custom.

With requireJs optimizer it calls this 2 functions (thefirst is called twice, and the second once):

 $.cleanData = function(elems) {
     for (var i = 0, elem; (elem = elems[i]) != null ; i++) {
          try {
             $(elem).triggerHandler("remove");
             // http://bugs.jquery.com/ticket/8235
           } catch (e) {}
         }
      _cleanData(elems);
  };

  jQuery.cleanData = function(elems) {
      var events;
      for (var i = 0, elem; (elem = elems[i]) != null; i++) {
        events = jQuery._data(elem, "events");
        if (events && events.$destroy) {
          jQuery(elem).triggerHandler('$destroy');
        }
      }
      originalCleanData(elems);
    };

If i remove the two implementation of jQuery.cleanData then it works after requireJs, but that not a solution. The problem happens after a state change in angular, which does not finish execution because of the exception and then mess up.

Here is the js of the Angular directive:

        define('misc/directives/fileUpload', ['../app'], function(app) {
            return app.directive('fileUpload', function() {
                return {
                    restrict: 'A',
                    template: '<input type="file" name="files[]">',
                    scope: {
                        onAdd: '=onAdd',
                        options: '=options'
                    },
                    link: function($scope, $element, $attrs) {
                        if ($attrs.multiple != null ) {
                            $element.find('input').attr('multiple', 'multiple');
                        }
                        return $element.fileupload(angular.extend({
                            autoUpload: false
                        }, $scope.options)).on('fileuploadprocessdone', function(e, data) {
                            return $scope.$apply($scope.onAdd(data.files));
                        }).on('$destroy', function() {
                            return $element.fileupload('destroy');
                        });
                    }
                };
            }).directive('fileUploadPreview', function() {
                return {
                    restrict: 'A',
                    scope: {
                        uploadFile: '=uploadFile'
                    },
                    link: function($scope, $element, $attrs) {
                        return $scope.$watch('uploadFile', function(file) {
                            $element.empty();
                            if (file != null ? file.preview : void 0) {
                                return $element.append(file.preview);
                            }
                        });
                    }
                };
            });
        });

What can cause this issue and what can we do to fix it? Is the call of return $element.fileupload('destroy'); necessary? It seems that cleanData are internal jquery methods, and we should now relay on what they do or if they are here see this question. Any ideas ?

regards Peter.

Community
  • 1
  • 1
Peter.K
  • 51
  • 2
  • 7

1 Answers1

0

as far as I can see, you do not need to call destroy here, since - as you said - JQuery is already taking care of it as soon as the element is removed from the DOM.

If your scenario in Angular is for example a change of the partial, then that might be the case.

The error message also indicates that the element does not have the fileupload applied anymore, since it got already removed before.

So far my assumptions.


Two further comments from my side:

  • What was the reason you have created your own angular directives when blueimp already does that on its own?

  • I would definitely check the requirejs setup since the behaviour should be the same in optimized and non-optimized mode.

rainerhahnekamp
  • 1,087
  • 12
  • 27