Alon Weissfeld
Alon Weissfeld

Reputation: 1325

Is it possible to write data to a locally json file with nothing but angular?

I'm trying to write data to a json file after hitting "Submit" on an html formly-form using only angular, but nothing is happening. I know I can read a json file using angular but not sure on creating files. onSubmit() in controller:

function onSubmit() {
    $scope.save = function() {
        $http.post('./temp/sample_data.json', JSON.stringify($scope.model)).then(function(data) {
            $scope.msg = 'Data saved';
        });
    };
};

html:

<form name="form" ng-submit="onSubmit()" novalidate>
    <formly-form model="model" fields="fields"></formly-form><br/>
    <button type="submit">Submit</button>
</form>

The sample_data.json isn't created and if I create an empty file it does not fill up with the data as well. The $scope.model defenitly contains data. If anyone can help, it will be very appreciated. Thanks, Alon.

Upvotes: 37

Views: 87130

Answers (6)

Velko Ivanov
Velko Ivanov

Reputation: 83

Ok, I'm digging in the past here, but the question is still relevant, judging by me looking for it today.

The accepted answer is the right one, I just want to add this implementation that works in Angular 15, from within a button click handler, without adding an actual element to the DOM and also sets the name of the file for download. It's dealing with a .csv file, but it is the same for .json too.

onExportButtonClick() {
  // Render the CSV file content
  let textResult = 'column1,column2,column3\n';
  textResult += ... generate text content ...

  // Create a blob from the CSV file content
  const blob = new Blob([textResult], { type: 'text/csv' });

  // Create a link to the blob
  const link = document.createElement('a');
  link.href = window.URL.createObjectURL(blob);
  link.download = 'generated_filename.csv';
  link.click();
}

And in the template (with Angular Material):

<button mat-raised-button
        color="primary" (click)="onExportButtonClick()">
  <mat-icon>save_alt</mat-icon>
  Export
</button>

Clicking on this button initiates a download of the generated file.

Upvotes: 1

AnthonyW
AnthonyW

Reputation: 1998

The following code adds a download button for a JSON object.

Note: wrapping a button with an anchor tag is not recommended for HTML 5 yet it works in Chrome which is all I needed. YMMV.

HTML:

<a download="my-json-object.json" [href]="dataUri">
  <button>Download</button>
</a>

Typescript:

  get dataUri(): SafeUrl {
    const jsonData = JSON.stringify(this.dataSource);
    const uri = 'data:application/json;charset=UTF-8,' + encodeURIComponent(jsonData);
    return this.sanitizer.bypassSecurityTrustUrl(uri);
  }

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1075337

Is it possible to write data to a locally json file with nothing but angular?

No. Even if you're running the page from the local file system (e.g., file://myfile.html) or from a local webserver (e.g., http://localhost/myfile.html or http://host-on-my-intranet/myfile.html), you still have no means of directly writing to a file from browser-hosted JavaScript code.

Two choices:

  1. Send it to something (e.g., a server) that can write it out, or

  2. Provide it as a data: URI (if feasible in your case) that the user can right-click and choose "save as..."

    Here's how you create a data: URI for some JSON text:

    var uri = "data:application/json;charset=UTF-8," + encodeURIComponent(theJSON);
    

Full Example of #2:

var theData = {
  foo: "bar"
};
var theJSON = JSON.stringify(theData);
var uri = "data:application/json;charset=UTF-8," + encodeURIComponent(theJSON);

var a = document.createElement('a');
a.href = uri;
a.innerHTML = "Right-click and choose 'save as...'";
document.body.appendChild(a);

Upvotes: 38

King Friday
King Friday

Reputation: 26096

Since this is not possible you could try another route. Your $scope.save was not being invoked by the way, only assigned.

$scope.save = function() {
  localStorage.model = JSON.stringify($scope.model);
};
function onSubmit() {
  $scope.save();
  $scope.msg = 'saved';
};

To get your model back do this on init:

if (localStorage.model)
  $scope.model = JSON.parse(localStorage.model);

Upvotes: 3

Alex McMillan
Alex McMillan

Reputation: 17952

You can't access the local filesystem (directly) from Javascript. This is enforced for security reasons (and makes sense when you think about it!).

Local file access with javascript

Upvotes: 5

Quentin
Quentin

Reputation: 944217

No.

Angular runs client side.

If you want to write data to the server (even one on the same computer as the browser) then you need server side code to do it.

Upvotes: 5

Related Questions