javascriptjqgridjqgrid-formatter

How to add custom formatter when the code is generated on the backend and sent to the view as a JSON in jQgrid?


I am using jQgrid and I'm building it's content from PHP and send it to the view as a JSON. Below is a snippet of the PHP code I am using currently:

$colFormats[] = [
    'index'     => 'actions',
    'name'      => 'actions',
    'width'     => 70,
    'editable'  => false,
    'formatter' => 'show_btn',
    'sortable'  => false,
    'align'     => 'center'
];

foreach ($classMedata->getFieldNames() as $key => $value) {
    $colFormats[] = [
        'index' => $classMedata->getCollection().'.'.$value,
        'name'  => $value,
        'width' => 100,
    ];
}

return $this->render('IntegrationBundle:api-logs:index.html.twig', [
        'colFormats' => json_encode($colFormats),
        'colNames'   => json_encode($colNames),
]);

This is the Javascript code I have on the view:

<script type="text/javascript">
    var show_btn = function (cellVal, options, rowObject) {
        return '<input style="height:22px;" type="button" value="Show" onclick="" />';
    };

    $(function () {
        $("#grid").jqGrid({
            url: '/sf/api-logs',
            datatype: "json",
            colNames: {{ colNames|raw }},
            colModel: {{ colFormats|raw }},
            width: 980,
            height: 300,
            pager: "#gridpager",
            toppager: true,
            hoverrows: true,
            shrinkToFit: true,
            autowidth: true,
            rownumbers: true,
            viewrecords: true,
            rowList: [10, 20, 50, 100],
            data: [],
            rownumWidth: 50,
            sortable: true,
            jsonReader: {
                root: 'rows',
                page: 'page',
                total: 'total',
                records: 'records',
                cell: '',
                repeatitems: false
            },
            loadComplete: function (data) {
                if (data.records === 0) {
                    $("#load_grid").addClass("info_msg").html($("<span>", {
                        "class": "grid-empty",
                        "text": "No results were found."
                    })).delay(800).fadeIn(400);
                }
            }
        });
    });
</script>

When PHP render the view I can see the proper JS code for colNames and colModel:

colNames: ["Actions", "ID", "Object", ...],
colModel: [{
    "index": "actions",
    "name": "actions",
    "width": 70,
    "editable": false,
    "formatter": "show_btn",
    "sortable": false,
    "align": "center"
}, 
{"index": "ApiLogs.id", "name": "id", "width": 100}, 
{"index": "ApiLogs.dataObject","name": "dataObject","width": 100}, ...

But instead of see the button rendered on the colum Actions I see a undefined word. I am not sure where is my mistake here. Can any help?

I have read the docs and also this post and I think I am doing it right but it's not because of the issue explained above.


Solution

  • The most comfortable form of formatter is the string form like formatter: "myFormatter". You know "predefined formatters" like formatter: "integer", formatter: "date" and so on. I suggest you to register your custom formatter as the "predefined formatters" and set it on the backend.

    To do this you need just extend the

    $.fn.fmatter.myFormatter = function (cellValue, options, rowData, addOrEdit) {
        // the code of formatter (the same as the custom formatter)
        return '<input style="height:22px;" type="button" value="Show" />';
    };
    $.fn.fmatter.myFormatter.unformat = function (cellValue, options, elem) {
        // the code of unformatter, like
        // return $(elem).text();
    };