Declarative class serving up FileDownload

I am trying to generate a FileDownload widget from a parameter in a declarative-style class, but am unable to get it to work.

Including the widgets dictionary that maps my parameter ‘select’ to widgets.FileDownload results in the error:

AttributeError: type object ‘FileDownload.param’ has no attribute ‘value’

What am I missing here?

import param
import panel as pn
import numpy as np
import pandas as pd

pn.extension()

class CustomExample(param.Parameterized):

    select = param.Action(lambda x: x._getData_requested(), label='Get Data')

    def __init__(self, **params):
        super().__init__(**params)
        np.random.seed(5)
        self.df = pd.DataFrame(np.random.randint(100, size=(100, 6)),
                          columns=list('ABCDEF'),
                          index=['R{}'.format(i) for i in range(100)])
        
    def _getData_requested(self):
        print('data requested')
        from io import StringIO
        sio = StringIO()
        self.df.to_csv(sio)
        sio.seek(0)
        self.value = sio
        return sio
        
pn.Param(CustomExample.param, widgets={
    'select': pn.widgets.FileDownload}
    )
    
custom = CustomExample()
pn.panel(custom).servable()

As far as I can determine, there is no param that maps to FileDownload, so it must be explicitly instantiated in a declarative class. Here is a working example:

import param
import panel as pn
import numpy as np
import pandas as pd

pn.extension()


class CustomExample(param.Parameterized):

    select = param.Action(lambda x: x.do_cool_stuff(), label='Cool Stuff!')

    def __init__(self, **params):
        super().__init__(**params)
        np.random.seed(5)
        self.df = pd.DataFrame(np.random.randint(100, size=(100, 6)),
                               columns=list('ABCDEF'),
                               index=['R{}'.format(i) for i in range(100)])

    def do_cool_stuff(self):
        print('doing something cool!')

    def _getData_requested(self):
        print('data requested!')
        from io import StringIO
        sio = StringIO()
        self.df.to_csv(sio)
        sio.seek(0)
        self.value = sio
        return sio

    def create_view(self):
        widgets = pn.Param(
            self,
            name='Data Viewer',
            parameters=['select']
        )
        # Must explicitly instantiate FileDownload widget as there
        # is no param that maps to it.
        widget = pn.widgets.FileDownload(
            callback=pn.bind(self._getData_requested), filename='file.csv',
            button_type='primary', label='Download')
        column = pn.Column(widgets, widget)
        return column


custom = CustomExample()
pn.panel(custom.create_view).servable()