We can customize the component templates used by FilePond to render the user interface.

The createFilePondEntryList function returns the default template used by FilePond to render the user interface.

Templating Basics

The template returned by createFilePondEntryList() is a JavaScript object tree that describes the user interface.

Objects in the tree are of type TemplateNode, these are either an ElementNode, ComponentNode, or SwitchNode.

ElementNode

An ElementNode describes an element, for example:

{
    tag: 'button',
    attrs: {
        type: 'button',
        onclick: () => {
            console.log('Hello World!');
        }
    },
    children: 'Click me!'
}

ComponentNode

An ComponentNode describes a Svelte component, for example:

{
    component: 'TextInput',
    props: {
        type: 'email',
        oninput: (detail) => {
            console.log('Hello World!',detail);
        }
    }
}

SwitchNode

A switch node allows choosing different render paths depending on context data.

{
    if: {
        test: ({ entry }) => !!entry.file,
        then: {
            tag: 'span',
            children: 'Is file '
        }
    },
    else: {
        tag: 'span',
        children: 'Is not a file'
    }
}

Included presets

These are helper functions that append a rich component to the template.

Image view

We can use the appendEntryImageView helper function to add an image preview. This will show a preview of added images.

import { defineFilePond } from 'filepond';
import { locale } from 'filepond/locales/en-gb.js';
import { createFilePondEntryList, appendEntryImageView } from 'filepond/templates';

// Add image view to default template
const template = createFilePondEntryList();
appendEntryImageView(template, {
    // Image view options
});

defineFilePond({
    locale,

    // Set custom template
    EntryListView: {
        template,
    },
});

Video view

We can use the appendEntryVideoView helper function to add a video preview. This will show a video player when videos are added that are supported by the browser.

import { defineFilePond } from 'filepond';
import { locale } from 'filepond/locales/en-gb.js';
import { createFilePondEntryList, appendEntryImageView } from 'filepond/templates';

// Add video view to default template
const template = createFilePondEntryList();
appendEntryVideoView(template, {
    // Video view options
});

defineFilePond({
    locale,

    // Set custom template
    EntryListView: {
        template,
    },
});

Example use cases

Handle click on a file

In this example we add a click event listener to the entry item name, when clicked the browser will download the file.

We import and use the withNodeTree helper function to make it easier to modify the default FilePond template returned by createFilePondEntryList.

To prepare the download link we use the ObjectURLView which automatically creates an ObjectURL for each file which we can then use in our link.

<form action="/upload" method="POST">
    <label for="my-file">Document</label>
    <file-pond>
        <input id="my-file" type="file" name="files" multiple required />
    </file-pond>

    <button type="submit">Upload</button>
</form>

<style>
    file-pond::part(download-link) {
        color: currentColor;
        pointer-events: all;
    }
</style>

<script type="module">
    import { defineFilePond } from 'filepond';
    import { locale } from 'filepond/locales/en-gb.js';
    import { ObjectURLView } from 'filepond/extensions/object-url-view.js';
    import { withNodeTree, createFilePondEntryList } from 'filepond/templates';

    // Create the default template
    const template = createFilePondEntryList();

    // Replace the file-info-main component with an anchor when we have an ObjectURL
    withNodeTree(template).update('file-info-main', (node) => {
        node.children = {
            // When we have our ObjectURL we render an anchor
            if: {
                test: ({ entry }) => !!entry.extension.ObjectURLView?.url,
                then: {
                    tag: 'a',
                    children: '{{entry.name}}',
                    attrs: ({ entry }) => ({
                        part: 'download-link',
                        download: entry.name,
                        href: entry.extension.ObjectURLView.url,
                    }),
                },
            },
            // If we don't have an ObjectURL we render a span
            else: {
                tag: 'span',
                children: '{{entry.name}}',
            },
        };
    });

    defineFilePond({
        locale,

        // Load ObjectURLView extension
        extensions: [ObjectURLView],

        // Set custom template
        EntryListView: {
            template,
        },
    });
</script>

While it does create a less visible interaction pattern, we can also add the click listener to the entry item itself.

In this situation, to offer the file as a download, we’ll use the downloadFile function as shown in this article on handling file downloads.

In the example below we don’t need the ObjectURLView extension as we’re creating and revoking the URL when we click the link.

import { defineFilePond } from 'filepond';
import { locale } from 'filepond/locales/en-gb.js';
import { createFilePondEntryList, withNodeTree } from 'filepond/templates';

// Create the default template
const template = createFilePondEntryList();

// Add onclick attribute to the entry component
withNodeTree(template).update('entry', (node) => {
    // Backup current props function
    const computeEntryPropsWithContext = node.props;

    // Set our custom props function
    node.props = (context) => ({
        // Compute props for context
        ...computeEntryPropsWithContext(context),

        // Add our event handler
        onclick: function (e) {
            // Ignore controls
            if (e.target.nodeName === 'BUTTON') {
                return;
            }

            // Download the file
            downloadFile(context.entry.file);
        },
    });
});

defineFilePond({
    locale,

    // Set custom template
    EntryListView: {
        template,
    },
});

// Helper function to download files
function downloadFile(file) {
    // Create a link and set the URL using `createObjectURL`
    const link = document.createElement('a');
    link.style.display = 'none';
    link.href = URL.createObjectURL(file);
    link.download = file.name;

    // It needs to be added to the DOM so it can be clicked
    document.body.appendChild(link);
    link.click();

    // To make this work on Firefox we need to wait
    // a little while before removing it.
    setTimeout(() => {
        URL.revokeObjectURL(link.href);
        link.parentNode.removeChild(link);
    }, 0);
}