How do you access data in AIO method?

Hey everyone! I was just trying to play around with the AIO components to make an opinionated Excel Download button that I could use across all of the pages in my Dash application. The construction would be something like the following:

class ExcelDownloadAIO(html.Div):  # html.Div is the parent element
    # :param df: Pandas DataFrame to be written in Excel (or eventually a dictionary
    #            that maps out the hierarchy, placement, and formatting of the file)
    # :param filename: Default filename for Excel file
    # :param filename_input_props: (Optional) Override default arguments for filename_input
    # :param download_button_props: (Optional) Override default arguments for download_button
    # :param download_component_props: (Optional) Override default arguments for download_component

    # Set of functions that create pattern-matching callbacks of the subcomponents
    class ids:
        filename_input = lambda aio_id: {
            "component": "ExcelDownloadAIO",
            "subcomponent": "filename_input",
            "aio_id": aio_id,
        }  # dbc.Input component
        download_button = lambda aio_id: {
            "component": "ExcelDownloadAIO",
            "subcomponent": "download_button",
            "aio_id": aio_id,
        }  # dbc.Button component
        download_component = lambda aio_id: {
            "component": "ExcelDownloadAIO",
            "subcomponent": "download_component",
            "aio_id": aio_id,
        }  # dcc.Download component
        status = lambda aio_id: {
            "component": "ExcelDownloadAIO",
            "subcomponent": "status",
            "aio_id": aio_id,
        }  # dcc.Store component

    # Make the ids class a public class
    ids = ids

    # Parameters to pass into the ExcelAIO Component
    def __init__(
        self,
        data,  # Pandas DataFrame (eventually full dictionary mapping)
        filename_props={},
        download_button_props={},
        download_component_props={},
        status_props={},
        aio_id={},
    ):
        # Create a unique AIO id if one is not passed
        aio_id = aio_id if aio_id else str(uuid.uuid4())

        self.data = data
        # Create / reconcile default parameters with user inputted values
        filename_props_user = filename_props.copy()
    
        filename_props.update({
            "placeholder": "Filename",
            "debounce": True,
            "type": "text",
        })
        filename_props.update(filename_props_user)


        download_button_props = (
            download_button_props.copy() if download_button_props else {}
        )
        if "size" not in download_button_props:
            download_button_props["size"] = "sm"
        if "className" not in download_button_props:
            download_button_props["className"] = "btn-secondary"

        download_component_props = (
            download_component_props.copy() if download_component_props else {}
        )

        super().__init__(
            [  # Equivalent to `html.Div([...])`
                dbc.Row(
                    dbc.Form(
                        [
                            dbc.InputGroup(
                                [
                                    dbc.Input(
                                        id=self.ids.filename_input(aio_id),
                                        **filename_props
                                    ),
                                    dbc.InputGroupText(".xlsx"),
                                ],
                                size="sm",
                                className="mb-3",
                            ),
                            html.Div(
                                dbc.Button(
                                    "Download",
                                    id=self.ids.download_button(aio_id),
                                    **download_button_props
                                ),
                                className="d-grid",
                            ),
                            dcc.Download(
                                id=self.ids.download_component(aio_id),
                            ),  # **download_component_props)
                            dcc.Store(id=self.ids.status(aio_id), **status_props),
                        ],
                    ),
                    className="d-flex justify-content-center",
                ),
            ]
        )

    # Handles filename validation on form submission:
    # @callback(
    #     Output(),
    #     Input(),
    #     Input(),
    # )

    # Handles download callback:
    @callback(
        Output(ids.status(MATCH), "data"),
        Input(ids.download_button(MATCH), "n_clicks"),
        State(ids.filename_input(MATCH), "value"),
        prevent_initial_call=True,
    )
    def xlsx_download(n_clicks, filename):
        
        temp_file = NamedTemporaryFile()

        # with pd.ExcelWriter(temp_file, engine="xlsxwriter") as writer:

        return dcc.send_file(temp_file.name)

Now, my question is that when I would use this AIO in the layout of the other app, what I envisioned was something along these lines: ExcelDownloadAIO(data=df), but I don’t quite know how to access the df Pandas dataframe in the xlsx_download callback? Thanks! :slight_smile:

As an edit to this post: I’m also not sure if I’m using the TemporaryFile component correctly, but that’s a bridge I can cross when I figure out how to get the data itself into the callback.

All-in-One Components | Dash for Python Documentation | Plotly