Загрузка файлов с angularjs и blueimp jquery fileupload?

Проведя несколько часов в поисках, я так и не смог найти решения. Суть проблемы:

Есть форма, в которой можно загружать файлы. Пример:
jsfiddle

Задача: нужно сделать так, чтобы юзер мог добавлять файлы (новые input[type=file]). Пример:
jsfiddle

Так вот, в чем проблема. Первый пример - работает. А второй - нет. Как будто просто не срабатывает функция submit. С чем это может быть связано?
  • Вопрос задан
  • 5710 просмотров
Решения вопроса 1
AMar4enko
@AMar4enko
Не смогу вам дать полностью правильное решение, но дам направление.
Дело в том, что у директивы data-file-upload есть внутренняя очередь файлов, связанная с самим uploader'ом. В первом примере выбор файла добавляет новый элемент в эту очередь. Происходит это потому, что в момент линковки директивы в DOM уже есть input[type="file"].
Во втором случае инпуты появляются тогда, когда отрабатывает ng-repeat, и data-file-upload некуда привязать событие добавления в очередь при линковке.

В целом, вы выбрали немного неверную модель работы с этим плагином.
Вот мой рабочий пример:
define(['app', 'lodash'], function(app, lodash) {
  return app.directive('fileUploader', function() {
    return {
      require: '?ngModel',
      replace: false,
      templateUrl: '/themes/main/assets/admin/js/views/directives/FileUploader.html',
      link: function($scope, element, attrs, ngModel) {
        $scope._files = [];
        $scope._uploaderOptions = {};
        if (ngModel) {
          ngModel.$render(function() {
            if (!angular.equals($scope._file, ngModel.$viewValue)) {
              return $scope._files = ngModel.$viewValue;
            }
          });
        }
        attrs.$observe('options', function(value) {
          return $scope._uploaderOptions = $scope[value];
        });
        return $scope.$on('fileuploaddone', function(event, data) {
          return $scope.$apply(function() {
            $scope._files = $scope._files.concat(data.result.files);
            event.targetScope.clear(data.files);
            if (ngModel) {
              return ngModel.$setViewValue($scope._files);
            }
          });
        });
      }
    };
  });
});

А это шаблон, который в директиве используется.
<div class="file-uploader">
  <ul class="tiles row-fluid">
    <li class="span3 tile" ng-repeat="file in _files">
      <div class="row-fluid information">
        <div class="span12">
          <div class="preview">
            <a ng-if="file.fileMetadata.thumbnailUrl"
               ng-href="{{file.uri}}"
               title="{{file.name}}" target="_blank">
              <img data-ng-src="{{file.fileMetadata.thumbnailUrl}}" width="48" alt="">
            </a>
          </div>
          <div class="info">
            <p class="name">{{file.name}}<br/><small>{{file.size | formatFileSize}}</small></p>
          </div>
        </div>
      </div>
    </li>
  </ul>
  <div file-upload="_uploaderOptions" ng-class="{'fileupload-processing': processing() || loadingFiles}">
    <div class="row-fluid fileupload-buttonbar">
      <div class="span12">
        <!-- The fileinput-button span is used to style the file input field as button -->
        <span class="btn btn-small btn-success fileinput-button" ng-class="{disabled: disabled}">
            <i class="glyphicon glyphicon-plus"></i>
            <span>Добавить...</span>
            <input type="file" name="files[]" multiple ng-disabled="disabled">
        </span>
      </div>
    </div>
    <!-- The table listing the files available for upload/download -->
    <ul class="tiles row-fluid">
      <li class="span3 tile" ng-repeat="file in queue"
          ng-class="{'processing': file.$processing(),'pending': file.$state() == 'pending'}">
        <div class="row-fluid information">
          <div class="span12">
            <div class="preview">
              <a ng-if="file.fileMetadata.thumbnailUrl"
                 ng-href="{{file.uri}}"
                 title="{{file.name}}" target="_blank">
                <img data-ng-src="{{file.fileMetadata.thumbnailUrl}}" width="48" alt="">
              </a>
            </div>
            <div class="info">
              <p class="name">{{file.name}}<br/><small>{{file.size | formatFileSize}}</small></p>
              <strong ng-show="file.error" class="error text-danger">{{file.error}}</strong>
            </div>
          </div>
        </div>
        <div class="row-fluid progress-bar" ng-show="file.$state() == 'pending'">
          <div class="progress progress-small progress-success active fade"
               ng-class="{pending: 'in'}[file.$state()]"
               file-upload-progress="file.$progress()">
            <div class="bar" ng-style="{width: num + '%'}"></div>
          </div>
        </div>
      </li>
    </ul>
  </div>
</div>

Смысл в том, что у нас в шаблоне всегда есть одна кнопка "Добавить", нажатие на нее обрабатывает сам uploader.
После нажатия на нее он добавит выбранный файл в очередь (в моем случае еще и загрузку начнет, потому что у меня автостарт используется). После того, как файл загрузится, сработает событие 'fileuploaddone', которое я ловлю, добавляю файл, который был загружен, к себе в список, а из очереди загрузчика удаляю.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы