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?

2

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

Comments

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;

2 Comments

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.
Thanks, this got me on the right track. Adding the functions to the $scope did the trick

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.