angularjs - ng-file-upload не привязывает модель к динамически создаваемой HTML-форме

Я хочу загрузить файл изображения из динамически сгенерированной HTML-формы, используя ng-repeat. Я использую модуль ng-file-upload для загрузки одного файла изображения (https://github.com/danialfarid/ng-file-upload). Когда я загружаю файл из статического HTML, он работает нормально. Но когда я пытаюсь загрузить файл из динамически сгенерированного HTML, он не работает должным образом. Файл не загружается, а также выдает ошибку в консоли Firefox следующим образом:

Error: Argument 2 of FormData.append is not an object.

Форма успешно отправлена, если мы назначаем ng-модель управления файлом, установленную на ноль. Например; если

<input name='img' type='file' value='' ng-model='data.imageFile' 'ngf-select' accept='image/*' />

а также

$scope.data.imageFile = null;

затем другие параметры будут отправлены службой HTTP и сохранены в базе данных в обычном режиме, но файл не будет загружен.

Есть ли способ назначить файловый объект для ввода [тип = файл] в этом случае динамически сгенерированного HTML??

Код PLUNKER создается здесь

http://plnkr.co/edit/S7hnVJnuDjWUMQ6PYewk?p=preview


person kishor10d    schedule 29.07.2015    source источник
comment
Попробуйте ng-model=$parent.data.imageFile. Возможно, вы добавляете его в другую область. В качестве обходного пути вы можете добавить директиву ngf-change=upload($file)   -  person danial    schedule 06.08.2015
comment
Я отказываюсь от этой идеи, которую использовал раньше, и использую ng-repeat в самом представлении. Теперь он просто работает нормально, но есть еще одна ошибка в плагине ng-upload, и я также нашел решение для этого.   -  person kishor10d    schedule 11.08.2015


Ответы (1)


Да, есть способ назначить тип ввода = файл для динамически сгенерированного HTML. Генерируется не только динамически при загрузке страницы, но и при добавлении нового типа ввода = файла через angular. Я только что сделал это, и это сработало!!! и я так взволнован, что публикую все трюки здесь. Все, что я прошу взамен, это, пожалуйста, проголосовать, когда вы заработаете в своем решении. И вопрос, и ответ сейчас на 0 баллов, но я могу доказать, что это рабочее решение.

     <input type="file" class="form form-control" placeholder="Section Image" file-model2="fileUploadFile2[getImageIndex(c.ChapterNbr, $index)][$index]" />

Обратите внимание, что у вас есть двухмерный массив, и этот файл ввода = входит в ng-repeat внутри ng-repeat, динамически добавляется, когда пользователь нажимает кнопку + Add.

с угловой стороны в getImageIndex:

        var chIndex = 0;
        var sIndex = 0;

        $scope.getImageIndex = function (chNbr, sectionNbr) {
            for (var i = 0; i < $scope.chapters.length; i++) {
                if ($scope.chapters[i].ChapterNbr == chNbr) {
                    chIndex = i;
                    sIndex = sectionNbr;
                    return i;
                };
            };
        };

Это сделано исключительно для получения индексов (первого и второго измерения, специфичных для моей настройки). Я использую директиву, размещенную где-то в StackOverflow, за которую я благодарен, чтобы фактически получить байты файла и информацию, и это выглядит так:

       .directive('fileModel2', ['$parse', function ($parse) {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                element.bind('change', function (e) {
                    $parse(attrs.fileModel2)
                    .assign(scope, element[0].files[0]);
                    scope.$apply();
                    scope.getFile2(scope.$eval(attrs.indexNumber));
                });
            }
        };
    }])
    .factory('fileReaderFactory', function ($q, $log) {
        return {
            onLoad: function (reader, deferred, scope) {
                return function () {
                    scope.$apply(function () {
                        deferred.resolve(reader.result);
                    });
                };
            },
            onError: function (reader, deferred, scope) {
                return function () {
                    scope.$apply(function () {
                        deferred.reject(reader.result);
                    });
                };
            },
            onProgress: function (reader, scope) {
                return function (event) {
                    scope.$broadcast("fileProgress",
                        {
                            total: event.total,
                            loaded: event.loaded
                        });
                };
            },
            getReader: function (deferred, scope) {
                var reader = new FileReader();
                reader.onload = this.onLoad(reader, deferred, scope);
                reader.onerror = this.onError(reader, deferred, scope);
                reader.onprogress = this.onProgress(reader, scope);
                return reader;
            },

            readAsDataURL: function (file, scope) {
                var deferred = $q.defer();

                var reader = this.getReader(deferred, scope);
                reader.readAsDataURL(file);

                return deferred.promise;
            }
        }
    }
    );

Директива запускает getFile2, который запускает Filereader для чтения байтов перед предварительным просмотром изображения. Наконец, чтобы просмотреть изображение:

         $scope.getFile2 = function () {
            console.log($scope.fileUploadFile2[chIndex][sIndex]);
            if ($scope.fileUploadFile2[chIndex][sIndex]) {
                fileReaderFactory.readAsDataURL($scope.fileUploadFile2[chIndex][sIndex], $scope)
                    .then(function (result) {
                        $scope.chapters[chIndex].Sections[sIndex].sectionImgPreview = result;
                    });
            }
        };

и вот html для предварительного просмотра изображения:

     <img ng-if="s.sectionImgPreview" class="img-responsive" ng-src="{{s.sectionImgPreview}}" alt="" onerror="this.src='@Url.Content("~/Content/Images/ToyApp.png")';" />

На этом этапе $scope.fileUploadFile2[chIndex][sIndex] готов к отправке на серверную часть, которая, в моем случае, является контроллером C#, который принимает весь JSON, содержащий главы и разделы курса, двоичные файлы изображений и видео, текст и html в сложный класс, который, в свою очередь, будет хранить информацию в схеме базы данных.

person Yogi    schedule 21.12.2015