Programatically exporting Collections as CSV with Wix Velo (Code)

Hi everyone

After a lot of research I have finally found a solution to this problem.

Custom element code:

class CSVDownloader extends HTMLElement {
    static get observedAttributes() {
        return ['csv-data'];
    }

    attributeChangedCallback(name, oldValue, newValue) {
        if (name === 'csv-data') {
            this.csvContent = newValue;
            this.querySelector('#download-button').style.display = 'block'; // Zeigt den Button an
        }
    }

    constructor() {
        super();
        this.innerHTML = `
            <style>
                /* Disregard */
            </style>
            <button id="download-button" style="display:none;">Daten herunterladen</button>
        `;

        this.querySelector('#download-button').addEventListener('click', () => this.downloadCSV());
    }

    downloadCSV() {
        let encodedUri = encodeURI("data:text/csv;charset=utf-8," + this.csvContent);
        let link = document.createElement("a");
        link.setAttribute("href", encodedUri);
        link.setAttribute("download", "Your_File_Name.csv");
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    }



}

customElements.define("csv-downloader", CSVDownloader);

Frontend-Code:

import wixData from 'wix-data';

export function exportButton_onClick(event) {
    wixData.query("YourCollectionName")
        .limit (1000)
        .find()
        .then(results => {
            let csvContent = "Field1,Field2,Field3,Field4\n"; // CSV-Header Names

            // Datenzeilen hinzufĂĽgen
            results.items.forEach(item => {
                let row = `"${item.field1}","${item.field2}","${item.field3}","${item.field4}"\n`; // Passen Sie die Felder an Ihre Sammlung an
                csvContent += row;
            });

            // Setzen des 'csv-data' Attributs am benutzerdefinierten Element
            $w("#csvDownloader").setAttribute("csv-data", csvContent);
        })
        .catch(err => {
            console.error(err);
        });
}

FYI: You need to have a regular Button “#exportButton” on the same page as the custom element. The custom element is invisible.

Hope this helps someone :slight_smile:

4 Likes

Another version from 2022…

Alternative ???..

And what about here…(year → 2020) ?

There are many ways of how to get the goal.

Questions:
-What is different on your solution ?
-Which advantages do your solution provide?
-Disatvantages?
-Something new?

Anyway good job!

Hey can you please help me with that ?

i cant see the download button… :frowning_face:

class CSVDownloader extends HTMLElement {
    static get observedAttributes() {
        return ['csv-data'];
    }

    attributeChangedCallback(name, oldValue, newValue) {
        console.log(`Attribute changed: ${name}, from: ${oldValue}, to: ${newValue}`);
        if (name === 'csv-data') {
            this.csvContent = newValue;
            this.querySelector('#download-button').style.display = 'block'; // Show the button
            console.log('CSV data updated, showing download button.');
        }
    }

    constructor() {
        super();
        console.log('CSVDownloader constructed.');
        this.innerHTML = `
<button id="download-button" style="background-color: #4CAF50; border: none; color: white; padding: 15px 32px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; margin: 4px 2px; cursor: pointer; border-radius: 8px;">Download</button>
        `;

        this.querySelector('#download-button').addEventListener('click', () => this.downloadCSV());
        console.log('Download button click event listener added.');
    }

    downloadCSV() {
        console.log('Preparing to download CSV...');
        let encodedUri = encodeURI("data:text/csv;charset=utf-8," + this.csvContent);
        let link = document.createElement("a");
        link.setAttribute("href", encodedUri);
        link.setAttribute("download", "Your_File_Name.csv");
        document.body.appendChild(link);
        console.log('Downloading CSV...');
        link.click();
        document.body.removeChild(link);
        console.log('CSV downloaded.');
    }
}

customElements.define("csv-downloader", CSVDownloader);
console.log('CSVDownloader custom element defined.');

front page:

export function exportButton_onClick(event) {
    wixData.query("foodOrders")
        .limit (1000)
        .find()
        .then(results => {
            let csvContent = "Field1,Field2,Field3,Field4\n"; // CSV-Header Names

            // Datenzeilen hinzufĂĽgen
            results.items.forEach(item => {
                let row = `"${item.field1}","${item.field2}","${item.field3}","${item.field4}"\n`; // Passen Sie die Felder an Ihre Sammlung an
                csvContent += row;
            });
              
            // Setzen des 'csv-data' Attributs am benutzerdefinierten Element
            $w("#csvDownloader").setAttribute("csv-data", csvContent);
        })
        .catch(err => {
            console.error(err);
        });
}

My button is called exportButton but i still cant see the download button.

You’ll have to add a regular Wix Button on the same page you added the custom element and then name it according to the code.

This is what I did on my page but I can’t see any button showing in the custom element: \
what can be the reason?

do I have to set attributes manually? or maybe change the custom file name?

Awesome stuff. Might also want to consider using a dataframe library like dataframe-js. Then you can write a generic and reusable function that doesn’t need the field names customized for each collection.