title: jQuery File Upload in AngularJS
body: <p>I'm trying to upload a file with <a href="http://blueimp.github.io/jQuery-File-Upload/">jQuery File Upload</a> in combination with angularJS. </p>
  
  <p>I have a multistep form, this are 2 steps of my multistep form:</p>
  
  <pre><code>&lt;div ng-switch="step"&gt;
      &lt;div ng-switch-when="1"&gt;
          &lt;h1&gt;Identity&lt;/h1&gt;
          &lt;form name="steponeForm" data-file-upload="options" enctype="multipart/form-data" novalidate autocomplete="off"&gt;
              &lt;input type="submit" ng-click="next(steponeForm.$valid)" value="next" /&gt;&lt;br&gt;
  
              &lt;span class="button fileinput-button" ng-class="{disabled: disabled}"&gt;
                  &lt;input type="file" id="fileupload" name="files[]" multiple="" &gt;
              &lt;/span&gt;
              &lt;button type="button" class="btn btn-primary start" data-ng-click="submit()"&gt;
                  &lt;span&gt;Start upload&lt;/span&gt;
              &lt;/button&gt;
  
              &lt;input ng-model="application.lastName" string-pattern required type="text" placeholder="{{ 'Last name'|translate }} *" name="appname" id="appname" /&gt;
              &lt;div ng-show="steponeForm.$submitted || steponeForm.appname.$touched"&gt;
                  &lt;div class="error" ng-show="steponeForm.appname.$error.required"&gt;Last name is required.&lt;/div&gt;
                  &lt;div class="error" ng-show="steponeForm.appname.$error.stringPattern"&gt;Doesn't look like a text.&lt;/div&gt;
              &lt;/div&gt;
  
              &lt;input type="submit" ng-click="next(steponeForm.$valid)" value="next" /&gt;
          &lt;/form&gt;
      &lt;/div&gt;
  
      &lt;div ng-switch-when="2"&gt;
          &lt;h1&gt;Studies&lt;/h1&gt;
          &lt;form name="steptwoForm" novalidate autocomplete="off"&gt;
              &lt;input type="submit" ng-click="previous()" value="previous" /&gt;
              &lt;input type="submit" ng-click="next(steptwoForm.$valid)" value="next" /&gt;
  
              &lt;fieldset class="input-group"&gt;
                  &lt;legend translate&gt;Lower secondary studies&lt;/legend&gt;
                  &lt;em&gt;Last obtained degree&lt;/em&gt;
  
                  &lt;input ng-model="application.LowerSecondaryStudies.degreeTitle" type="text" placeholder="Degree Title" name="moreLowerSecondaryStudies-degreetitle" id="lwsappdegreetitle" /&gt;
                  &lt;input ng-model="application.LowerSecondaryStudies.educationAuthority" type="text" placeholder="Education authority" name="moreLowerSecondaryStudies-educationauthority" id="lwsappeducationauthority" /&gt;
                  &lt;input ng-model="application.LowerSecondaryStudies.graduationYear" style="padding: 0.5278em; width: 100%;" type="number" min="1960" max="2015" value="2015" placeholder="Graduation year" name="moreLowerSecondaryStudiesgraduationyear" id="lwsappgraduationyear" /&gt;
                  &lt;div ng-show="steptwoForm.$submitted || steptwoForm.moreLowerSecondaryStudiesgraduationyear.$touched"&gt;
                      &lt;div class="error" ng-show="steptwoForm.moreLowerSecondaryStudiesgraduationyear.$error.number"&gt;Must be valid year.&lt;/div&gt;
                  &lt;/div&gt;
              &lt;/fieldset&gt;
  
              &lt;input type="submit" ng-click="previous()" value="previous" /&gt;
              &lt;input type="submit" ng-click="next(steptwoForm.$valid)" value="next" /&gt;
          &lt;/form&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>In my custom js file I have:</p>
  
  <pre><code>jQuery('#fileupload').fileupload({
      dataType: 'json'
  });
  </code></pre>
  
  <p>In my controller (angularjs) I have:</p>
  
  <pre><code>$scope.options = {
      maxFileSize: 5000000,
      type: "POST",
      acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i
  };
  </code></pre>
  
  <p>As you can see I call the submit() function on Start upload, but that doesn't trigger anything. I'm also not getting any errors in my browser console. What am I missing? </p>
  
  <p><strong>UPDATE:</strong></p>
  
  <p>I don't have a submission function in my controller.js . I thought this was standard added with <code>jquery.fileupload-angular.js</code> . They also didn't specify a submit function <a href="https://github.com/blueimp/jQuery-File-Upload/blob/master/angularjs.html">here</a> in the example <em>jQuery fileupload + angularjs</em>.</p>
  
  <p>The declaration of my module in <strong>app.js</strong>:</p>
  
  <pre><code>var app = angular.module('dxs-vkgroupApp', ['ngRoute', 'gettext'])
  .config(function($routeProvider, $httpProvider, $locationProvider){
      // send all requests payload as query string
      $httpProvider.defaults.transformRequest = function(data){
          if (data === undefined) {
              return data;
          }
          return jQuery.param(data);
      };
  
      // set all post requests content type
      $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
  
      // all routes
      $routeProvider
          .when('/edit.php/submissions/', {
              templateUrl: viewsPath.views + 'submissions.html',
              controller: 'SubmissionOverviewController'
          })
          .when('/edit.php/submission/show/:fid/', {
              templateUrl: viewsPath.views + 'submission.html',
              controller: 'ShowSubmissionController'
          })
          .when('/edit.php/submission/delete/:fid/', {
              templateUrl: viewsPath.views + 'delete-submission.html',
              controller: 'DeleteSubmissionController'
          })
          .when('/wp-admin/', {
              controller: 'RouteDeciderController',
              template: '&lt;div ng-include="getTemplateUrl()"&gt;&lt;/div&gt;'
          })
          .when('/:l/submission/new/:jid', {
              templateUrl: viewsPath.views + 'new-submission.html',
              controller: 'StepController'
          })
          .when('/:l/projects/', {
              templateUrl: viewsPath.views + 'projects.html',
              controller: 'ProjectsOverviewController'
          }).otherwise({
              controller: 'RouteDeciderController',
              template: '&lt;div ng-include="getTemplateUrl()"&gt;&lt;/div&gt;'
          });
  
      $locationProvider.html5Mode(true);
  })
  .run(function (gettextCatalog, $location) {
      var curr_path = $location.path();
      var result = curr_path.split("/");
      var language = result[1];
  
      gettextCatalog.setCurrentLanguage(language);
      gettextCatalog.debug = true;
  });
  </code></pre>
  
  <p>In my <strong>controller.js</strong> I have amongst other things:</p>
  
  <pre><code>/**
   * Deals with advancing, going back or finishing the multi step form
   *
   * @param $scope
   * @param $http
   * @param $routeParams
   * @constructor
   */
  function StepController($scope, $http, $routeParams)
  {
      // inits
      $scope.application = {};
      $scope.application.children = [];
  
      // counters
      $scope.childCounter = 0;
      $scope.moreLowerSecondaryStudiesCounter = 0;
      $scope.moreHigherSecondaryStudiesCounter = 0;
      $scope.moreHigherShortTermEducationCounter = 0;
      $scope.moreHigherLongTermEducationCounter = 0;
      $scope.moreAdditionalStudiesSpecialtyCounter = 0;
      $scope.moreAdditionalStudiesThesisCounter = 0;
      $scope.languageCounter = 0;
      $scope.experienceCounter = 0;
  
      // select options
      $scope.languageOptions = ['--select--', 'very good', 'good', 'notions', 'no notion'];
  
      // languages
      // @todo make the default list dynamic instead of hardcoded (problem is, the variable expressions wont get accepted in the select attributes)
      //$scope.languages = ['dutch', 'french', 'english', 'german'];
  
      $scope.job_id = $routeParams.jid;
  
      $scope.step = 1;
  
      $scope.noneSelected = function (type) {
          switch(type)
          {
              case 'appcontact':
                      if(!$scope.application.contact){
                          return true;
                      }
                      else
                      {
                          return !($scope.application.contact.relations || $scope.application.contact.employees || $scope.application.contact.jobad || $scope.application.contact.website || $scope.application.contact.other)
                      }
                  break;
              case 'appworklocation':
                      if(!$scope.application.worklocation){
                          return true;
                      }
                      else
                      {
                          return !($scope.application.worklocation.roeselare || $scope.application.worklocation.brussel || $scope.application.worklocation.merelbeke)
                      }
                  break;
          }
      };
  
      $scope.next = function($valid){
          if(!$valid)
          {
              $scope.step = $scope.step;
          }
          else if($scope.step == 2)
          {
              $scope.inputgrouperror = false;
  
              // special check for 6 input groups (input fields)
              if(check())
              {
                  $scope.step += 1;
              }
              else
              {
                  $scope.inputgrouperror = true;
                  $scope.step = $scope.step;
              }
          }
          else
          {
              $scope.step += 1;
          }
  
          window.scrollTo(0,0);
      };
  
      $scope.previous = function(){
          $scope.step -= 1;
          window.scrollTo(0,0);
      };
  
      $scope.finish = function($valid){
          if(!$valid)
          {
              $scope.step = $scope.step;
          }
          else
          {
              $http.post('new-submission', { id: $scope.job_id, application: $scope.application })
                  .success(function(data, status, headers, config){
                      window.location.href = data.redirect_url;
                  });
          }
      };
  }
  
  function check() {
      var check = false;
      jQuery.each(jQuery('fieldset.input-group'), function () { //loops through all fieldsets
          if (!check) { //are there no fieldsets with  3 filled input elements then check is false so far
              check = jQuery(this).find('input:text,[type^="number"]').filter(function () { //checks whether inputs are filled
                  return this.value != "";
              }).length &gt; 2; //If filled inputs &gt; 2 -&gt; check = true
          }
      });
  
      return check;
  }
  
  angular.module('dxs-vkgroupApp')
      .controller('StepController', StepController);
  </code></pre>