As my readers know, I've been updating some of my earlier Vue.js examples to demonstrate how they would work with Alpine.js. Normally I post these "conversions" when I see one of the Vue posts pop up in my stats. Today I noticed this entry was "trending" - Vue Quick Shot - Downloading Data as a File. I thought it would be a great candidate for showing an Alpine version. Let's take a look.

While I won't repeat everything from the previous post, I'll quickly cover how it worked. First, it makes use of the download attribute of the anchor tag. This will take a normal link operation and instead ask the browser to download the resource at the URL. To do this with client-side data, you can create an anchor tag with createElement, set it to point to your data, and then emulate a click event. I used this a few days ago in an Eleventy article: Adding Download Support in an Eleventy Site.

In the original article, I first demonstrated downloading a JSON file. But as most humans don't speak JSON, I then used Papa Parse to convert it to CSV. I'm going to follow the same flow for this update.

First Version - Downloading JSON Data #

For the first version, we're going to look at a tabular set of cats. I will not make you scroll past the gratuitous picture of a cat on a table. Heh, I lie:

Cat on a table

Ok, so our data:

	{"name":"Alese", "gender":"female", "age": 10},
	{"name":"Sammy", "gender":"male", "age": 12},
	{"name":"Luna", "gender":"female", "age": 8},
	{"name":"Cracker", "gender":"male", "age": 7},
	{"name":"Pig", "gender":"female", "age": 6}

The application begins by simply rendering this into a table. (Not a sortable or paginated one, but check out my other Alpine.js posts for examples of that.) I started off with this HTML:

<div x-data="app">
		<template x-for="cat in cats">
				<td x-text=""></td>
				<td x-text="cat.gender"></td>
				<td x-text="cat.age"></td>

Alpine is used to loop over the cats array. Here's the initial JavaScript:

document.addEventListener('alpine:init', () => {'app', () => ({
      {name:"Alese", gender:"female", age: 10},
      {name:"Sammy", gender:"male", age: 12},
      {name:"Luna", gender:"female", age: 8},
      {name:"Cracker", gender:"male", age: 7},
      {name:"Pig", gender:"female", age: 6}

Now I'm going to add a download button that will trigger the download process:

<button @click="download">Download</button>

I then added my handler. This code is a bit simpler than the previous version which added to anchor to the DOM, invisibly, and then clicked.

download() {
	let text = JSON.stringify(this.cats);
	let filename = 'cats.json';
	let element = document.createElement('a');
	element.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(text));
	element.setAttribute('download', filename);;

If you read my previous article involving Eleventy and downloads, the biggest difference here is creating the data URL string that has the original data encoded into a string. You can test this version yourself here:

See the Pen Alpine Data Save 1 by Raymond Camden (@cfjedimaster) on CodePen.

Second Version - Downloading CSV #

For the next version, we just need to convert the JSON data to CSV. Once again I'll use Papa Parse as it makes this trivial. Instead of

let text = JSON.stringify(this.cats);

We can use:

let text = Papa.unparse(this.cats);

I then made two more changes. First, the filename:

let filename = 'cats.csv';

And then the mime-type:

element.setAttribute('href', 'data:text/csv;charset=utf-8,' + encodeURIComponent(text));

That's literally the entire change. Now when clicking download you get a CSV that can be opened in Excel. My previous post had a screenshot of that but as this was before you could use Dark mode in Office, I figured I'd update it with a new one:

Excel sample output

Here's the entire example:

See the Pen Alpine Data Save 1 by Raymond Camden (@cfjedimaster) on CodePen.