Construct widget from param

I’m trying to create tabbed pane with Tabulator and widgets that will be filters for the table.
Currently this is what I have:

import io

import pandas as pd
import panel as pn
import param

editors = {
    'index': {'type': 'number'},
    'entity': {'type': 'autocomplete', 'values': True},
    'key': {'type': 'autocomplete', 'values': True},
    'value': {'type': 'input'},
    'special': {'type': 'input'},
    'issue': {'type': 'input'},
}

COLUMNS = {
    'General': ['index', 'description', 'suite', 'enable', 'issue', 'tech', 'freq', 'bw', 'duplex', 'carriers'],
    'Scenarios': ['index', 'entity', 'key', 'value', 'special', 'issue'],
    'Verdicts': ['index', 'channel', 'section', 'enable', 'key', 'metric', 'value', 'special', 'issue']
}

pn.extension()
pn.config.sizing_mode = 'stretch_width'


def contains_filter(df, pattern, column):
    if not pattern:
        return df
    return df[df[column].str.contains(pattern)]


class FilterBase(param.Parameterized):
    index = param.ObjectSelector()
    common_index = param.Boolean(default=True)

    def __init__(self, **params):
        self.param.index.default = pn.widgets.MultiChoice(name='Index')
        super().__init__(**params)

    def view(self):
        return self.index


class GeneralFilter(FilterBase):
    index = param.ObjectSelector()

    def __init__(self, **params):
        super().__init__(**params)


class ScenariosFilter(FilterBase):
    index = param.ObjectSelector()
    entity = param.ObjectSelector()
    key = param.String()

    def __init__(self, **params):
        self.param.entity.default = pn.widgets.MultiChoice(name='Entity')
        super().__init__(**params)

    def view(self):
        return pn.Column(
            super(ScenariosFilter, self).view(),
            self.entity,
            self.param.key,
        )


class VerdictsFilter(FilterBase):
    index = param.ObjectSelector()

    def __init__(self, **params):
        super().__init__(**params)


class InputDataBase(param.Parameterized):
    tabulator = param.Parameter()

    def __init__(self, group_by_index, name, filter_obj, **params):
        self.param.tabulator.default = pn.widgets.Tabulator(
            value=pd.DataFrame(columns=COLUMNS[name]),
            selectable=False,  # 'checkbox',
            show_index=False,
            groupby=['index'] if group_by_index else [],
            # layout='fit_data_stretch',
            # width=1000,
            # height=800,
            configuration={
                'groupStartOpen': [False],
                'groupToggleElement': "header",
            },
            # editors=editors,
            theme='site',
            sizing_mode="stretch_both"
        )
        super().__init__(**params)
        self._filter = filter_obj
        self._name = name
        self._add_filters()

    def _add_filters(self):
        self.tabulator.add_filter(self._filter.index, column='index')

    @pn.depends("tabulator.value", watch=True)
    def update_filters(self):
        self._filter.index.options = list(self.tabulator.value['index'].unique())

    def view(self):
        return pn.Row(
            pn.Column(self.tabulator, width=1400, height=880),
            pn.Card(self._filter.view(), title='Filters'),
            name=self._name
        )


class GeneralData(InputDataBase):
    tabulator = param.Parameter()

    def __init__(self, **params):
        super(GeneralData, self).__init__(
            group_by_index=False,
            name='General',
            filter_obj=GeneralFilter(),
            **params
        )

    def _add_filters(self):
        super(GeneralData, self)._add_filters()


class ScenariosData(InputDataBase):
    tabulator = param.Parameter()

    def __init__(self, **params):
        super(ScenariosData, self).__init__(
            group_by_index=True,
            name='Scenarios',
            filter_obj=ScenariosFilter(),
            **params
        )

    def _add_filters(self):
        super(ScenariosData, self)._add_filters()
        self.tabulator.add_filter(self._filter.entity, column='entity')
        self.tabulator.add_filter(pn.bind(contains_filter, pattern=self._filter.param.key, column='key'))

    @pn.depends("tabulator.value", watch=True)
    def update_filters(self):
        super(ScenariosData, self).update_filters()
        self._filter.entity.options = list(self.tabulator.value['entity'].unique())


class VerdictsData(InputDataBase):
    tabulator = param.Parameter()

    def __init__(self, **params):
        super(VerdictsData, self).__init__(
            group_by_index=True,
            name='Verdicts',
            filter_obj=VerdictsFilter(),
            **params
        )

    def _add_filters(self):
        super(VerdictsData, self)._add_filters()


class DataTemplate(param.Parameterized):
    load_data = param.Action(label="Load Data")
    file_input = param.Parameter()

    def __init__(self, **params):
        self.param.file_input.default = pn.widgets.FileInput(accept='.csv', multiple=True)
        super().__init__(**params)
        self._input_data = {
            'general.csv': GeneralData(),
            'scenarios.csv': ScenariosData(),
            'verdicts.csv': VerdictsData()
        }
        self.load_data = self._load_data
        self.tabs_pane = pn.Tabs(*[v.view() for v in self._input_data.values()])
        self.template = pn.template.MaterialTemplate(title='Simplenario', theme=pn.template.DarkTheme)
        self.template.sidebar.append(pn.Column('## Data Load', self.file_input, self.param.load_data, width=270))
        self.template.main.append(self.tabs_pane)

    def _load_data(self, event):
        values = self.file_input.value
        files = self.file_input.filename
        if values is not None and files is not None:
            self.tabs_pane.loading = True
            for file, value in zip(files, values):
                string_io = io.StringIO(value.decode("utf8"))
                self._input_data[file].tabulator.value = pd.read_csv(string_io, keep_default_na=False, index_col=False)
            self.tabs_pane.loading = False

    def serve(self):
        self.template.servable()


data_template = DataTemplate()
data_template.serve()

It’s working but I feel that I’m doing something wrong.
I think I need to construct FilterBase class differently, but I tried many options to create widgets from params like “from_param” and param.ClassSelector but still I can’t figure out how to make “FilterBase view” method as pn.Param(self).

One more thing is when I tried to create pn.Param(self) and using widgets attribute, I can’t make it work with Tabulator’s add_filter method because it need to be a widget.

This is how it looks:

Thanks in advance.