Bug report: React slot renderer not working in child rows

Bug report: React slot renderer not working in child rows

JussiJussi Posts: 5Questions: 0Answers: 0

Using React Datatables, I have following slot rendering component:

function BoolToYesNo({ value }) {
    if (value === true) {
        return (
            <>
                <i className="fa fa-check-circle success"></i> Yes
            </>
        );
    } else {
        return (
            <>
                <i className="fa fa-times-circle-o danger"></i> No
            </>
        );
    }
}

When the component is rendered in "whole row", it displays correctly:

When the component is rendered in "child row", it doesn't display correctly:

Replies

  • allanallan Posts: 65,206Questions: 1Answers: 10,804 Site admin

    How are you creating the child row?

    Allan

  • JussiJussi Posts: 5Questions: 0Answers: 0

    I just import this:

    import "datatables.net-responsive-dt";

    And then I use these options:

        const dataTableOptions = {
            retrieve: true,
            serverSide: true,
            processing: true,
            searching: true,
            orderCellsTop: true,
            responsive: {
                details: {
                    type: "column",
                    target: 0,
                },
            },
            ajax: postAjaxConfig,
            columns: dtColumns,
            order: [[22, "desc"]],
            columnDefs: [
                {
                    className: "dtr-control",
                    orderable: false,
                    targets: 0,
                },
                {
                    defaultContent: "",
                    targets: "_all",
                },
            ],
        };
    

    And here is the actual DataTable to be rendered:

            <DataTable
                ref={dataTableRef}
                slots={{
                    Type: (data, row) => getType(data),
                    NotificationSendingAllowed: (data, row) => <BoolToYesNo value={data} />,
                    AllowEmailNotifications: (data, row) => <BoolToYesNo value={data} />,
                    AllowSMSNotifications: (data, row) => <BoolToYesNo value={data} />,
                    SanityValidationErrors: (data, row) => <SanityValidationErrors errors={data} />,
                    Toiminnot: (data, row) => (
                        <Toiminnot cellData={data} rowData={row} dataTableRef={dataTableRef} />
                    ),
                }}
                options={dataTableOptions}
                className="table table-hover table-bordered table-condensed nowrap dataTable dtr-inline collapsed"
            >
                <thead>
                    <tr>
                        {dtColumns.map((col, index) =>
                            col.visible !== false && col.name ? (
                                <th key={index}>{getColName(col)}</th>
                            ) : (
                                <th key={index}></th>
                            )
                        )}
                    </tr>
                </thead>
            </DataTable>
    

    Finally, when the table is rendered, I reduce the width of the page so that "Notifications allowed", "Emails allowed" and "SMS notifications allowed" columns are automagically moved to the child rows.

  • JussiJussi Posts: 5Questions: 0Answers: 0

    Regarding my issue, I tried to inspect some datatables.net-react code.

    In the following function, the if statement blocks contain identical code:

    function slotRenderer(cache, slot) {
        return function (data, type, row, meta) {
            if (slot.length === 4) {
                let result = slot(data, type, row, meta);
                return result['$$typeof'] ? renderJsx(cache, result) : result;
            }
            else if (slot.length === 3) {
                // The function takes three parameters so it allows for
                // orthogonal data - not possible to cache the response
                let result = slot(data, type, row, meta);
                return result['$$typeof'] ? renderJsx(cache, result) : result;
            }
            // Otherwise, we are expecting a JSX return from the function every
            // time and we can cache it. Note the `slot as any` - Typescript
            // doesn't appear to like the two argument option for `DataTableSlot`.
            return slotCache(cache, () => slot(data, row));
        };
    }
    

    Are those identical code blocks a bug?

  • allanallan Posts: 65,206Questions: 1Answers: 10,804 Site admin

    Oh, this is for Responsive's child rows, not your own?

    Try using the listHiddenNodes renderer for Responsive, an example for which is available here.

    Allan

  • JussiJussi Posts: 5Questions: 0Answers: 0

    I'm importing the React version of DataTable:

    import DataTable from "datatables.net-react";

    This is what my 'responsive' option looks like:

            responsive: {
                details: {
                    type: "column",
                    target: 0,
                    renderer: DataTable.Responsive.renderer.listHiddenNodes(),
                },
            },
    

    I get "TypeError: Cannot read properties of undefined (reading 'renderer')"

  • JussiJussi Posts: 5Questions: 0Answers: 0

    "Oh, this is for Responsive's child rows, not your own?"

    Yes.

Sign In or Register to comment.