Shovon Choudhury
Shovon Choudhury

Reputation: 11

Datatable custom filtering with Server Side with Editor

I am having some trouble integrating some custom functionalities with Datatable and Datatable Editor at the same time. Without server-side processing my current functionalities works perfectly but I want to be able to implement server-side filtering with Editor.

With server-side filtering these work: 1.Pagination 2.Global Search 3.Sorting 4.Row reorder 5.Dynamic Page length

With server-side filtering these don't work: 1.Custom column input filtering 2.Custom footer select filtering

My serverside script for Datatable and Editor:

Editor::inst($db, 'article_categories')
            ->fields(
                Field::inst('article_categories.id')->validator('Validate::numeric'),
                Field::inst('article_categories.name')->validator('Validate::notEmpty'),
                Field::inst('article_categories.description'),
                Field::inst('article_categories.rowOrder')->validator('Validate::numeric')
            )
            ->on('preCreate', function ($editor, $values) {
                if (!$values['article_categories']['rowOrder']) {
                    $next = $editor->db()->sql('select IFNULL(MAX(rowOrder)+1, 1) as next FROM article_categories')->fetch();
                    $editor->field('article_categories.rowOrder')->setValue($next['next']);
                } else {
                    $editor->db()
                        ->query('update', 'article_categories')
                        ->set('rowOrder', 'rowOrder+1', false)
                        ->where('rowOrder', $values['article_categories']['rowOrder'], '>=')
                        ->exec();
                }
            })
            ->on('preRemove', function ($editor, $id, $values) {
                $order = $editor->db()
                    ->select('article_categories', 'rowOrder', array('id' => $id))
                    ->fetch();
 
                $editor->db()
                    ->query('update', 'article_categories')
                    ->set('rowOrder', 'rowOrder-1', false)
                    ->where('rowOrder', $order['rowOrder'], '>')
                    ->exec();
            })
            ->process($request->all())
            ->json();

My client-side script:

Default config:

jQuery(function () {
    $.extend(true, $.fn.dataTable.defaults, {
        serverSide: true,
        fixedHeader: true,
        searchDelay: 800,
        paging: true,
        processing: true,
        pageLength: 10,
        info: true,
        dom: "Blfrtip",
        select: true,
        responsive: true,
        lengthMenu: [
            [10, 25, 50, -1],
            [10, 25, 50, "All"],
        ],
    });
});

Datatable and Editor setup:

var editor;
jQuery(function () {
    //Editor
    editor = new $.fn.dataTable.Editor({
        table: "#article-category",
        ajax: {
            url: "article-categories",
            type: "POST",
        },
        fields: [
            {
                label: "Order:",
                name: "article_categories.rowOrder",
                type: "hidden",
                fieldInfo:
                    "This field can only be edited via click and drag row reordering.",
            },
            {
                label: "FAQ Category Name:",
                name: "article_categories.name",
            },
            {
                label: "Description (optional):",
                name: "article_categories.description",
                type: "textarea",
            },
        ],
    });
 
    //Datatable
    var table = $("#article-category").DataTable({
        ajax: {
            url: "article-categories",
            type: "POST",
        },
        rowReorder: {
            dataSrc: "article_categories.rowOrder",
            editor: editor,
        },
        buttons: cms.editorFormButtons(editor),
        initComplete: function () {
            cms.headerInputFilter("article-category", this.api(), [1, 2]);
            cms.footerSelectFilter(this.api(), [1, 2]);
        },
        columns: [
            {
                data: "article_categories.rowOrder",
                name: "article_categories.rowOrder",
                className: "reorder no-inline",
            },
            {
                data: "article_categories.name",
                name: "article_categories.name",
            },
            {
                data: "article_categories.description",
                name: "article_categories.description",
            },
        ],
    });
 
    //Inline Editor
    cms.inlineEdit("article-category", editor);
 
    editor
        .on("postCreate postRemove", function () {
            table.ajax.reload(null, false);
        })
        .on("initCreate", function () {
            editor.field("article_categories.rowOrder").enable();
        })
        .on("initEdit", function () {
            editor.field("article_categories.rowOrder").disable();
        });
});

Custom functions:

let footerSelectFilter = function (table, columns) {
    if (typeof columns != "undefined" && typeof table != "undefined") {
        table.columns(columns).every(function () {
            var column = this;
            var select = $('<select><option value=""></option></select>')
                .appendTo($(column.footer()).empty())
                .on("change", function () {
                    var val = $.fn.dataTable.util.escapeRegex($(this).val());
 
                    column
                        .search(val ? "^" + val + "$" : "", true, false)
                        .draw();
                });
 
            column
                .data()
                .unique()
                .sort()
                .each(function (d, j) {
                    select.append(
                        '<option value="' + d + '">' + d + "</option>"
                    );
                });
        });
    }
};
 
let headerInputFilter = function (target, table, searchableColumns) {
    if (
        typeof searchableColumns != "undefined" &&
        typeof target != "undefined" &&
        typeof table != "undefined"
    ) {
        $("#" + target + " thead tr")
            .clone(true)
            .addClass("filters")
            .appendTo("#" + target + " thead");
 
        var i = 0;
        var api = table;
        api.columns()
            .eq(0)
            .each(function (colIdx) {
                if (
                    searchableColumns.includes(
                        $(api.column(colIdx).header()).index()
                    )
                ) {
                    var cell = $(".filters th").eq(
                        $(api.column(colIdx).header()).index()
                    );
                    var title = $(cell).text();
                    $(cell).html(
                        '<input style="width:100% !important" type="text" placeholder="' +
                            title +
                            '" />'
                    );
                    $(
                        "input",
                        $(".filters th").eq(
                            $(api.column(colIdx).header()).index()
                        )
                    )
                        .off("keyup change")
                        .on("keyup change", function (e) {
                            e.stopPropagation();
                            $(this).attr("title", $(this).val());
                            var regexr = "({search})";
 
                            var cursorPosition = this.selectionStart;
                            api.column(colIdx)
                                .search(
                                    this.value != ""
                                        ? regexr.replace(
                                              "{search}",
                                              "(((" + this.value + ")))"
                                          )
                                        : "",
                                    this.value != "",
                                    this.value == ""
                                )
                                .draw();
 
                            $(this)
                                .focus()[0]
                                .setSelectionRange(
                                    cursorPosition,
                                    cursorPosition
                                );
                        });
                } else {
                    return true;
                }
            });
    }
};
 
let editorFormButtons = function (editor) {
    if (typeof editor != "undefined") {
        return [
            {
                extend: "create",
                editor: editor,
                formButtons: [
                    {
                        label: "Save",
                        fn: function () {
                            var that = this;
                            this.submit(function () {
                                that.close();
                            });
                        },
                    },
                ],
            },
 
            {
                extend: "edit",
                text: "Edit",
                editor: editor,
                formButtons: [
                    {
                        label: "Save & close",
                        fn: function () {
                            var that = this;
                            this.submit(function () {
                                that.close();
                            });
                        },
                    },
                    {
                        label: "Update",
                        fn: function () {
                            this.submit(function () {
                                editor.edit(
                                    table.rows({ selected: true }).indexes()
                                );
                            });
                        },
                    },
                ],
            },
 
            {
                extend: "remove",
                editor: editor,
                formButtons: [
                    {
                        label: "Delete",
                        fn: function () {
                            var that = this;
                            this.submit(function () {
                                that.close();
                            });
                        },
                    },
                ],
            },
        ];
    }
};
 
let inlineEdit = function (target, editor) {
    if (typeof target != "undefined" && typeof editor != "undefined") {
        $("#" + target + "").on(
            "click",
            "tbody td:not(.no-inline)",
            function (e) {
                if (
                    $(this).hasClass("editor-edit") ||
                    $(this).hasClass("control") ||
                    $(this).hasClass("select-checkbox") ||
                    $(this).hasClass("dataTables_empty")
                ) {
                    return;
                }
                editor.inline(this, {
                    submit: "allIfChanged",
                });
            }
        );
    }
};
 
module.exports = {
    headerInputFilter,
    footerSelectFilter,
    editorFormButtons,
    inlineEdit,
};

When I set server-side to false the custom functionalities I need works perfectly but I need these with server-side processing as it will significantly improve overall performance . I would appreciate any help and suggestion. Regards, Shovon Choudhury

Upvotes: 1

Views: 971

Answers (0)

Related Questions