2

I am new to angularjs and trying create an single page application. I have a home controller with very simple code. Something along the lines of this tutorial

Angular JS controller is initialized with code like:

var phonecatApp = angular.module('phonecatApp', []);
phonecatApp.controller('PhoneListCtrl', function ($scope) {
  $scope.phones = [
    {'name': 'Nexus S',
     '_id': 1,
     'snippet': 'Fast just got faster with Nexus S.'},
    {'name': 'Motorola XOOM™ with Wi-Fi',
     '_id': 2,
     'snippet': 'The Next, Next Generation tablet.'},
    {'name': 'MOTOROLA XOOM™',
     '_id': 3,
     'snippet': 'The Next, Next Generation tablet.'}
  ];
});

but in production data might not be so neatly packed. Now my problem is:

Can I create a download link to a JSON representation of my objects?

<li ng-repeat="phone in phones">
<a 
  href="data:text/json;charset=utf-8,{{encodeURIComponent(JSON.stringify(phone))}}" 
  download="{{phone._id}}.json">
    JSON
</a>
</li>

I basically want to access the current object phone with the formatting function encodeURIComponent(JSON.stringify(phone)).

Is there a way to do this neatly?

user3194532
  • 687
  • 7
  • 7
  • see this post [how-do-you-serve-a-file-for-download-with-angularjs-or-javascript](http://stackoverflow.com/questions/16514509/how-do-you-serve-a-file-for-download-with-angularjs-or-javascript) – Josh Pendergrass Nov 22 '15 at 14:01
  • [The post](http://stackoverflow.com/questions/16514509/how-do-you-serve-a-file-for-download-with-angularjs-or-javascript) explains a lot but left a few things open, that were needed here. – user3194532 Nov 22 '15 at 17:24

2 Answers2

2

I basically want to access the current object phone with the formatting function encodeURIComponent(JSON.stringify(phone)).

You simply add a method to your controller: working example (collections)

$scope.encodeJson = function(phone) {
  return encodeURIComponent(JSON.stringify(phone));
}

<a href="data:text/json;charset=utf-8,{{encodeJson(data)}}" download="{{filename}}">

You may also need sanitize the URL

For collections it's basically the same:

<p ng-repeat="item in collection">
  <a href="data:text/json;charset=utf-8,{{encodeJson(item)}}" download="{{item.id}}.json">
</p>

Additionally you may need remove the $$HashKey -added by ng-repeat- by using "track by item.id" syntax in the ng-repeat.

Another approach could be add those functions to the $scope itself and using them inside ng-* attributes.

$scope.encodeURIComponent = encodeURIComponent;
$scope.JSON = JSON;
Community
  • 1
  • 1
rnrneverdies
  • 15,243
  • 9
  • 65
  • 95
  • Thanks for the quick answer, but this is not that I was looking for. I'd rather like to calculate the representation on the fly than having two representations of the same data. – user3194532 Nov 22 '15 at 14:35
  • Thanks, this got me on the right track. Adding the functions to the $scope did the trick – user3194532 Nov 22 '15 at 17:21
2

Thanks to the suggestions of rnrneverdiesI added the following to the config

phonecatApp.config(['$compileProvider', function ($compileProvider) {
  $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|file|data|blob):/);
}]);

and these functions to the $scope in the controller

$scope.stripClone = function(obj) {
  if (null == obj || "object" != typeof obj) return obj;
  var copy = obj.constructor();
  for (var attr in obj) {
    if (obj.hasOwnProperty(attr) && attr != '$$hashKey') {
      var obj_attr = obj[attr];
      if (typeof obj_attr == "object"){
        copy[attr] = this.stripClone(obj_attr); 
      } else if (typeof obj_attr == "array"){
        copy[attr] =[];
        for(var i =0; i<obj_attr.length; i++){
          copy[attr].push(this.stripClone(obj_attr));
        }
      }else{
        copy[attr] = obj_attr;
      }
    }
  }
  return copy;
};
$scope.myEncodeJson = function(obj){
  return JSON.stringify(this.stripClone(obj));
};

I can now call these functions in the template to do the json magic I wanted:

<a ng-href="data:text/json;charset=utf-8,{{myEncodeJson(phone)}}

Thanks for your help

Community
  • 1
  • 1
user3194532
  • 687
  • 7
  • 7