Watching for updates from a class that does not inherit from Parameterized

I just started with Panel, so this might be a dumb question:

I am trying to make a dashboard from which I can upload some JSON files. These JSON files get ingested into to a custom MyDataset object which the dashboard aims to visualize in various ways (this class contains functions that can spit out pandas dataframes). This MyDataset class comes from another project and does not inherit from param.Parameterized. I currently have the following code to add new files to the dashboard:

class DatasetManager(param.Parameterized):
    
    file_input = pn.widgets.FileInput(accept='.json', multiple=True)
    dataset = MyDataset()
    view = param.Parameter()
    
    def __init__(self, **params):
        super().__init__(**params)
        self._create_view()
        
    def _create_view(self):
        self.view = pn.Column(
            "# Upload files",
            self.file_input
        )
        
    @param.depends("file_input.filename", watch=True)
    def _update_data(self, *event):
        if self.file_input.filename is None:
            return
        for filename, content in zip(self.file_input.filename, self.file_input.value):
            self.dataset.ingest_json(filename, json.loads(content.decode("utf-8")))
        
DatasetManager().view.servable()

How can I turn this code such that I can later make widgets that react to changes to the dataset?

Hi @mdorier

You can trigger and event on the dataset using self.param.trigger("dataset"). Then if you can .depends or .bind to the `dataset. There is an example below.

import json

import panel as pn
import param


class MyDataset:
    value: str = {}

    def ingest_json(self, filename, value):
        self.value = value


class DatasetManager(param.Parameterized):
    dataset = param.ClassSelector(class_=MyDataset)

    def __init__(self, **params):
        if not "dataset" in params:
            params["dataset"] = MyDataset()
        super().__init__(**params)

        self._file_input = pn.widgets.FileInput(accept=".json", multiple=True)
        pn.bind(self._update_data, self._file_input, watch=True)

        self.view = pn.Column("# Upload files", self._file_input)

    def _update_data(self, *event):
        if self._file_input.filename is None:
            return
        for filename, content in zip(self._file_input.filename, self._file_input.value):
            self.dataset.ingest_json(filename, json.loads(content.decode("utf-8")))
            self.param.trigger("dataset")  # this will raise the event signaling the dataset changed


manager = DatasetManager()

updates = pn.indicators.Number(name="Updates", value=0)


@param.depends(manager.param.dataset, watch=True)
def update_indicator(ds):
    if ds.value:
        updates.value += 1


@param.depends(manager.param.dataset)
def show_data(ds):
    return manager.dataset.value


pn.Column(manager.view, updates, show_data).servable()