Directive to create a[download] button
Solution 1
How about something like this: Fiddle
Here's the directive code:
module.directive('myDownload', function ($compile) {
return {
restrict:'E',
scope:{ getUrlData:'&getData'},
link:function (scope, elm, attrs) {
var url = URL.createObjectURL(scope.getUrlData());
elm.append($compile(
'<a class="btn" download="backup.json"' +
'href="' + url + '">' +
'Download' +
'</a>'
)(scope));
}
};
});
Controller:
module.controller('MyCtrl', function ($scope){
var data = {a:1, b:2, c:3};
var json = JSON.stringify(data);
$scope.getBlob = function(){
return new Blob([json], {type: "application/json"});
}
});
Solution 2
I ended up here trying to solve a similar issue. in my Angular page, I have a JSON retrieved via Ajax that is rendered as HTML, but I wanted the "raw" JSON to be downloadable via a link.
the issue with the OP's and most-voted approach is that the HTML DOM is manipulated within your controller, which kind of defeats the purpose of using MVVM. i think the reason you're doing all of that is because Angular blocks creation of links for blobs (by pre-pending 'unsafe:' to the resulting blob URL).
Fortunately, Angular provides a way to apply a whitelist certain URL prefixes so it will not be blocked when you use URL.createObjectURL()
...in this case, we include blob
here is my take on it running on JSFiddle
Related videos on Youtube
bsr
Updated on September 14, 2022Comments
-
bsr over 1 year
I got help to save json as file in client side here. Code is very short as in this fiddle.
var a = document.createElement('a'); a.download = "backup.json"; a.href = url; a.textContent = "Download backup.json"; document.getElementById('content').appendChild(a);
I was trying to create an angularjs directive so that it calls a method in scope to get the data. Along this line.
module.directive('myDownload', function ($compile) { return { restrict:'E', scope:{ getData:'&getData'}, link:function (scope, elm, attrs) { elm.append($compile( '<a class="btn" download="backup.json"' + 'href=' + scope.getData() + '>' + 'Download' + '</a>' )(scope)); } }; });
This doesn't work. How can make the linked fiddle into a directive?
-
bsr almost 11 yearswell, one small issue though. Is it possible to fetch new data whenever I click the link. I noticed getBlob() only calls once, initially. Is it possible?
-
mfelix almost 11 yearsIn that case I would start by binding the directive's scope to whichever data in your controller's scope can change the data that would be given by clicking the link. Then I would try using scope.$watch on those bound properties inside the directive's link function to make it regenerate the download link anytime any of them changes. That's what comes to mind, but maybe there's a better way.
-
bsr almost 11 yearsthanks you for all the effort.My intention was not to retrieve the data till it necessary. When I think about it, it may better to show another scree/preview using normal action, then use that data to do download url. Thanks again for your effort. Cheers.
-
Rafael almost 8 yearsWhat if the blob type differs?