Saving text to a client-side file using vanilla JS
Tags: showdev, tutorial, beginners
Published: 2020-04-17 13:49:12

---
title: Saving text to a client-side file using vanilla JS
published: true
date: 2020-04-17 13:30:00 UTC
tags: showdev, tutorial, beginners
canonical_url: https://robkendal.co.uk/blog/2020-04-17-saving-text-to-client-side-file-using-vanilla-js/
cover_image: https://robkendal.co.uk/img/saving%20to%20client-side%20files%20-%20blog%20post.png
---

![Blog header for the article on](https://robkendal.co.uk/img/saving%20to%20client-side%20files%20-%20blog%20post.png)

Another one of those 'born of an issue I stumbled across' sort of situations, I came across the need to save some data entered into a form (some configuration details into a textarea to be specific).

Sure, there are lots of means available to save something to the local machine of a user, but they tend to involve either less-than-ideal solutions such as a browser's local storage, a cookie, or even using the [HTML canvas blob](https://html.spec.whatwg.org/multipage/canvas.html).

## The need for simple solutions

There is a great article (if not a little out of date by now) by Eli Grey on [saving generated files on the client side](https://eligrey.com/blog/saving-generated-files-on-the-client-side/) that also discusses his excellent utility [FileSaver.js](https://github.com/eligrey/FileSaver.js), which utilises the very same canvas blob functions mentioned above.

However, for me, it seemed a little overblown to bring in _another_ utility dependency to perform a really simple task of creating a small text file and stashing it on the client's machine.

## A vanilla JS solution to client-side file saving

So here we are, a really simple way to create and save a file on the client side, from the browser, based on some information saved into a textarea.

First, the HTML...

```html
<fieldset>
  <legend>Enter some config details</legend>
  <textarea></textarea>
  <button id="btnSave">save config</button>
</fieldset>
```

Which renders the following no-frills elements in the browser (styling not shown for simplicity):

![Screenshot of the textarea and save button ready to save the file](https://robkendal.co.uk/img/config-file-save.jpg)

Now, for the JavaScript:

```javascript
const downloadToFile = (content, filename, contentType) => {
  const a = document.createElement('a');
  const file = new Blob([content], {type: contentType});
  
  a.href= URL.createObjectURL(file);
  a.download = filename;
  a.click();

  URL.revokeObjectURL(a.href);
};

document.querySelector('#btnSave').addEventListener('click', () => {
  const textArea = document.querySelector('textarea');
  
  downloadToFile(textArea.value, 'my-new-file.txt', 'text/plain');
});
```

What we've got going on here, is a plain, browser-native querySelector call that grabs our button with the id `btnSave`, attaches an event listener that fires on click — nothing too fancy here.

Where the magic (well, really simple magic) is in the 'downloadToFile' method above. We create a new anchor element and a new [Blob object](https://developer.mozilla.org/en-US/docs/Web/API/Blob) using the content and contentType arguments we passed in.

Next, we set the `href` element to the result of the `URL.createObjectURL()` method that creates a DOMString containing a URL that represents the file object we just made.

Finally, we trigger our new anchor element's click event, which kicks off the download process in the browser, before cleaning things up using the `URL.revokeObjectURL()` method.

## See it in action

You can [view the code in action](https://codepen.io/robkendal/pen/dyYMqMP) in my CodePen, or below in a handy iFrame.

{% codepen https://codepen.io/robkendal/pen/dyYMqMP %}

## Wrapping things up

And that's it. Nice and simple, gets the job done. Sometimes, the most straightforward solution is the best one if you need something lightweight that just works.

You might also like these articles that use plain old JS and CSS:

- [Funky text backgrounds with background-clip CSS](https://dev.to/kendalmintcode/funky-text-backgrounds-with-background-clip-css-56o7)
- [Creating unique, merged arrays using JavaScript's Set (and more)](https://dev.to/kendalmintcode/creating-unique-merged-arrays-using-javascript-s-set-and-more-l7m)
- [Configure Parcel JS and Babel to use JavaScript proposal class properties](https://dev.to/kendalmintcode/configure-parcel-js-and-babel-to-use-javascript-proposal-class-properties-1he3)
- [How to use arrow functions in JavaScript ES6](https://dev.to/kendalmintcode/how-to-use-arrow-functions-in-javascript-es6-2p55)