• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

AngularJS - custom directive na input type=file

Aruba Cloud PRO i VPS, Openstack, VMWare, MS Hyper-V
0 głosów
38 wizyt
pytanie zadane 16 marca w JavaScript przez KonTar Początkujący (440 p.)

Cześć! smiley

w AngularJS mam taki dziwny problem z przyciskiem "wybierz plik". Jak wybieram plik o tej samej nazwie po raz drugi i kolejny, to nie może się on załadować do przeglądarki do pamięci. Ogólnie widzę że zmiana nazwy pliku wyzwala jego upload, bo występuje wtedy changeEvent, a chciałbym żeby ładował plik za każdym razem, kiedy zamykane jest okienko.


Ktoś tu może jest przekozakiem z AngularJS/javascriptu i powie gdzie leży problem?laugh

Poniżej kod....

html

<input type="file" name="file" fileread="$ctrl.file" multiple="multiple" class="ng-isolate-scope">

fileupload.js

var main = angular.module('main');

main.directive("fileread", [function () {
    return {
        restrict: 'A',
        scope: {
            fileread: "="
        },
        link: function (scope, element, attributes) {
            element.bind("change", function (changeEvent) {
                scope.fileread = [];
                for (let i = 0; i < changeEvent.target.files.length; i++) {
                    scope.fileread.push({ fileName: changeEvent.target.files[i].name });
                }

                for (let i = 0; i < changeEvent.target.files.length; i++) {
                    let reader = new FileReader();
                    reader.onload = function (loadEvent) {
                        scope.$apply(() => {
                            scope.fileread[i].content = loadEvent.target.result.split(";base64,").pop();
                        });
                    };
                    reader.readAsDataURL(changeEvent.target.files[i]);
                }
            });
        }
    };
}]);

 

Z góry dziękuję za pomoc!
 

komentarz 16 marca przez ScriptyChris Mędrzec (191,540 p.)

Próbowałeś podpiąć się na input event (zamiast change)?

komentarz 6 dni temu przez KonTar Początkujący (440 p.)

Z tego co obserwuję to zastąpienie change na input nie zmienia działania samego mechanizmu :(

main.directive("fileread", [function () {
    return {
        restrict: 'A',
        scope: {
            fileread: "="
        },
        link: function (scope, element, attributes) {
            element.bind("input", function (inputEvent) {
                scope.fileread = [];
                for (let i = 0; i < inputEvent.target.files.length; i++) {
                    scope.fileread.push({ fileName: inputEvent.target.files[i].name });
                }

                for (let i = 0; i < inputEvent.target.files.length; i++) {
                    let reader = new FileReader();
                    reader.onload = function (loadEvent) {
                        scope.$apply(() => {
                            scope.fileread[i].content = loadEvent.target.result.split(";base64,").pop();
                        });
                    };
                    reader.readAsDataURL(inputEvent.target.files[i]);
                }
            });
        }
    };
}]);

2 odpowiedzi

0 głosów
odpowiedź 2 dni temu przez kozacko Obywatel (1,080 p.)
wybrane 1 dzień temu przez KonTar
 
Najlepsza

Wygląda na to, że plik nie jest ładowany do pamięci przeglądarki z powodu przypisywania do scope.fileread pustej tablicy za każdym razem, gdy zmieniasz plik. To powoduje usunięcie poprzednio wybranych plików z pamięci przeglądarki. Aby rozwiązać ten problem, możesz usunąć linię scope.fileread = []; i zmienić pętlę na:
 

for (let i = 0; i < changeEvent.target.files.length; i++) {
    scope.fileread.push({ fileName: changeEvent.target.files[i].name });
    let reader = new FileReader();
    reader.onload = function (loadEvent) {
        scope.$apply(() => {
            scope.fileread[i].content = loadEvent.target.result.split(";base64,").pop();
        });
    };
    reader.readAsDataURL(changeEvent.target.files[i]);
}

To powinno pozwolić zachować już wczytane pliki w pamięci przeglądarki i dodawać kolejne pliki do listy.

komentarz 2 dni temu przez KonTar Początkujący (440 p.)
Dzięki za podpowiedź! Generalnie pliki ładują się do pamięci, bo w inpucie mamy atrybut: multiple="multiple", więc wybieramy wiele plików za każdym razem, więc tutaj raczej nie musiałem nic zmieniać. Ogólnie udało się rozwiązać problem, ale to opisze może w odpowiedzi do pytania :)
+2 głosów
odpowiedź 2 dni temu przez KonTar Początkujący (440 p.)

Problem udało się rozwiązać na podstawie dwóch spostrzeżeń.

  • event "click" wywołujemy przed "change" na inputcie,
  • przez każdy event możemy odwołać się do konkretnego inputa przez "event.target".

Okazało się, że wystarczyło po każdym kliknięciu usuwać value z inputa, żeby każdy wskazany plik był tak jakby nowy. W skrócie trzeba było resetować aktualny stan inputa, żeby wywołał się change. Pewnie są lepsze sposoby na  to rozwiązanie, ale cóż...smiley

<input type="file" name="file" fileread="$ctrl.file" ng-click="$ctrl.cleanFileCache($event)" multiple="multiple" />
    $ctrl.cleanFileCache = function (clickEvent) {
        if (clickEvent.target.files.length > 0) {
            clickEvent.target.value = null;
            $ctrl.file = [];
        }
    };

 

Podobne pytania

0 głosów
3 odpowiedzi 164 wizyt
pytanie zadane 16 stycznia 2017 w JavaScript przez Captivity Obywatel (1,030 p.)
–1 głos
2 odpowiedzi 337 wizyt
0 głosów
0 odpowiedzi 152 wizyt
pytanie zadane 3 maja 2018 w JavaScript przez LockeLamora Użytkownik (740 p.)

90,823 zapytań

139,496 odpowiedzi

313,568 komentarzy

60,316 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...