Der kurze Weg

AngularJS Direktive Download Button

AngularJS Direktive - Download Button

AngularJS

Diese AngularJS Direktive wurde von uns entwickelt um einen html2pdf Service (/services/html2pdf) anzusprechen der aus übergebenen HTML fertige PDFs generiert und zurückschickt (zum Download). Die Idee dahinter ist die Antwort (das PDF) als base64 zu kodieren und über einen Link mit zum Download anzubieten <a href="data:application/pdf;base64,..."></a>. Das Attribut html enthält dabei den HTML Code der umgewandelt werden soll.
Wir haben diese Direktive dann erweitert und können statt dem Attribut html auch das Attribut url übergeben. Als Ergebnis muss diese URL (Schnittstelle) ein base64 kodiertes Dokument wiedergeben (inkl. mime-Typ) um diese Datei dann herunterzuladen. Auf Serverseite könnte die Datei zum Beispiel mit file_get_contents() eingelesen und mit base64_encode() kodiert werden.

Beim ersten klicken des Buttons wird die Datei angefordert (Button wird dabei disabled und Ladeicon wird angezeigt). Wenn der Ladevorgang abgeschlossen ist (also der AJAX Request) wird der Button wieder aktiv und stellt die Datei zum Download bereit.

Implementiert könnte es zum Beispiel so aussehen: 

<est-download label="Datenblatt 20" filename="datenblatt-20.pdf" url="//your-api.com/download/example/20">
</est-download>

Erforderlich:

  • Bootstrap (Style)
  • Jasny Bootstrap (btn-labeled)
  • AngularJS
  • FontAwesome (Icons)
App.directive('estDownload', function() {
return {
    restrict: 'E',
    template: '<span class="input-group-btn" ng-click="download()">' +
                            '<a class="btn btn-labeled btn-primary">' +
                                '<span id="icon" class="btn-label"><i class="fa fa-fw fa-download"></i></span>' +
                                '<span id="label"></span>' +
                            '</a></span>',
    scope: true,
    link: function(scope, element, attr) {
 
        var anchor = element.children()[0];
 
        anchor = angular.element(anchor).find('a');
        anchor.addClass(attr.class);
        anchor.find('#label').text(attr.label);
 
        var htmlIcon = anchor.find('#icon').html();
 
        // When the download starts, disable the link
        scope.$on('download-start', function() {
            angular.element(anchor).attr('disabled', 'disabled');
            anchor.find('#icon').html('<i class="fa fa-fw fa-refresh fa-spin"></i>');
        });
 
        // When the download finishes, attach the data to the link. Enable the link and change its appearance.
        scope.$on('downloaded', function(event, data) {
            angular.element(anchor).attr({
                href: data,
                download: attr.filename,
                target: 'blanc',
            })
                .removeAttr('disabled')
               // .text('Download')
                .removeClass('btn-primary')
                .addClass('btn-success');
 
            anchor.find('#icon').html(htmlIcon);
 
            // Also overwrite the download pdf function to do nothing.
            scope.download = function() { };
        });
    },
    controller: ['$scope','$rootScope', '$attrs', '$http', function($scope,$rootScope, $attrs, $http) {
        $scope.download = function() {
            $scope.$emit('download-start');
 
            function httpGetHtml2Pdf(html) {
                $http.post($rootScope.api + '/services/html2pdf', { 
                    html: html
                } ).success(function(data) {
                    $scope.$emit('downloaded', data.base64mime);
                });
            };
 
            if(typeof $attrs.html !== 'undefined')
            {
                httpGetHtml2Pdf($attrs.html);
            }
            else {
                $http.get($attrs.url).success(function(data) {
                    $scope.$emit('downloaded', data.base64mime);
                });
            }
        };
    }] 
  }
});