Recent Posts

Pages: 1 2 [3] 4 5 ... 10
21
I have verified that the code you provided is working correctly. Thank you.
22
Help for ParamQuery Pro / Re: Date column filter with lte, equal or gte
« Last post by paramvir on April 26, 2026, 07:14:33 am »
Upon re-evaluating the built-in capabilities of the grid, there is an even more efficient approach. UTC dates are natively supported by pqGrid, which eliminates the need for complex workarounds.

The Simplified Solution: ISO 8601 Compliance

You do not need to set up two-way column dependencies or manual conversions. By ensuring your data follows standard UTC formatting, the grid handles the heavy lifting automatically.

  • UTC Marking: Simply append a 'Z' to your UTC date strings (e.g., "2026-04-26 12:00:00Z"). This explicitly marks them as UTC.
  • Automatic Conversion: The grid will automatically detect the 'Z' suffix and convert the values to locally formatted dates for both the display and the filtering logic.
  • Native Formatting: Use the standard column.format option to define how you want the date to appear to the user.


Why this is the best approach:

  • No Custom Logic: There is no need for column.render or custom filtering comparison callbacks.
  • Native Performance: It utilizes the grid's internal optimized engine for handling date objects and timezones.
  • Consistency: The filter and the cell display stay perfectly synchronized with the user's local system time automatically.
23
Help for ParamQuery Grid (free version) / Re: Tool tips on Grpup level columns
« Last post by paramvir on April 25, 2026, 07:38:22 am »
You can achieve this by using the column.render callback to inject a title attribute into the cell, which will then display as a native browser tooltip.

Code: [Select]
render( ui ){
    return {
        //here we inject html title attribute in each cell.
        attr: {
            title: (ui.rowData.ActivityDescription || "" ).replace(/"/g, '"')
        }
    }
}

A quick optimization note:
I noticed you are manually using Intl.NumberFormat within the render callback while column.format is already defined. You can simplify this by using ui.formatVal inside your render function; this provides the already-formatted value based on your column settings, so you don't need to reformat it manually.
24
Help for ParamQuery Grid (free version) / Tool tips on Grpup level columns
« Last post by pbassey on April 25, 2026, 12:31:50 am »
I have the following grid code:

    var obj = {
        height: 540,
        width: '100%',
        dataModel: {
            location: "remote", //server side call
            dataType: "jsonp",
            method: "GET",
            url: "/APS/Activity/grid_Activity?yearValue=" + theYear + "&sourceValue=" + source, //URL
            getData: function (dataJSON) {
                var data = dataJSON.data;
                return { curPage: dataJSON.curPage, totalRecords: dataJSON.totalRecords, data: data };
            }
        },
        numberCell: { width: 40 },
        freezeCols: 1,
        flex: { one: true },
        rowBorders: false,
        colModel: [
            { dataIndx: 'KeyRec', title: 'KeyRec', hidden: true, editable: false },
            { dataIndx: 'SummKeyRec', title: 'SummKeyRec', hidden: true, editable: false },

            { dataIndx: 'ActivityYear', title: 'ActivityYear', hidden: true, editable: false },

            { dataIndx: 'grp', title: 'ActivityId', tpHide: true, editable: false, menuInHide: true, minWidth: 150 },
            { dataIndx: "ActivityId", title: "FAS Activity", editable: false, hidden: true, filter: { groupIndx: 'Region' } },

            { dataIndx: "Project", title: 'Project Code', valign: "top", editable: false, valign: "top", minWidth: 110 },
            { dataIndx: "Source", title: 'Source', valign: "top", editable: false, valign: "top", minWidth: 70 },
            { dataIndx: "ProjBud", title: 'Project Budget', valign: "top", format: '$ #,###,###.00', editable: false, summary: { type: "sum" }, valign: "top", align: "right", minWidth: 100 },

            {
                dataIndx: "YTD_Tot", title: 'YTD Through<br>@lastMonthName', halign: "center", valign: "top", format: '$ #,###,###.00', style: "background-color: lightyellow;",
                editable: false, summary: { type: "sum" }, valign: "top", align: "right", minWidth: 100, format: '$ #,###,###.00',
                render: function (ui) {
                    try {
                        const formattedAmount = new Intl.NumberFormat('en-US'
                            , { style: 'currency', currency: 'USD' }).format(ui.cellData); //format to USD
                        var ActivityID = ui.rowData.ActivityId;
                        var Project = ui.rowData.Project;
                        var Source = ui.rowData.Source;
                        var link = "";
                        if (doesNotContainUnassigned(Project)) {

                            link = "<span onClick=javascript:OpenTranWindow(" + "'" + ActivityID + "','" + Project + "','History','" + Source + "') style='cursor: pointer;'>"
                                + formattedAmount +
                                "</span>";
                        }
                        else {
                            link = "<span onClick=javascript:OpenTranWindow(" + "'" + ActivityID + "','','History','" + Source + "') style='cursor: pointer;'>"
                                + formattedAmount +
                                "</span>";
                        }


                        return link;
                    } catch (error) {
                        // Code to handle the error
                        //console.error('An error occurred:', error.message);
                        return "";
                    }

                }
            },
            //Define the link for the first month of Projections
            {
                dataIndx: "FirstColumn", title: '@ViewBag.curMonthName', editor: { type: 'textbox', attr: 'maxlength="12"' },
                valign: "top", format: '$ #,###,###.00', editable: true, summary: { type: "sum" }, align: "right", minWidth: 80,
                style: "background-color: lightyellow;",
                render: function (ui) {
                    try {
                        const formattedAmount = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(ui.cellData);
                        var ActivityID = ui.rowData.ActivityId;
                        var Project = ui.rowData.Project;

                        if (Project== null || Project.indexOf("Unassigned") >-1)  {//Project.includes("Unassigned")){
                            Project = '';
                        }
                        var Source = ui.rowData.Source;
                        var link = "<span onClick=javascript:OpenLastMonthWindow(" + "'" + ActivityID + "','" + Project + "','" + Source + "') style='cursor: pointer;'>"
                                + formattedAmount +
                                "</span>";

                        //}

                        return link;
                    } catch (error) {
                        // Code to handle the error
                        console.log('An error occurred:', error.message);
                        return "";
                    }

                }
            },
            {
                title: "Projection Months", align: "center", collapsible: { last: true, on: false },
                colModel: [

                    //Define all subsequent months here
                    @foreach (var month in Model)
                    {
                        @: { dataIndx: "@month.DataIndx", title: '@month.Title', editor: { type: 'textbox', attr: 'maxlength="12"' }, valign: "top", format: '$ #,###,###.00', editable: true, summary: { type: "sum" }, align: "right", minWidth: 80 },
                    }


                    {
                        dataIndx: "TP", title: 'Total<br>Projections', halign: "center", valign: "top", format: '$ #,###,###.00',
                        //style: "background-color: lightyellow;",
                        editable: false, summary: { type: "sum" }, valign: "top", align: "right", minWidth: 100, format: '$ #,###,###.00',
                        render: function (ui) {
                            try {
                                const formattedAmount = new Intl.NumberFormat('en-US'
                                    , { style: 'currency', currency: 'USD' }).format(ui.cellData); //format to USD
                                var ActivityID = ui.rowData.ActivityId;
                                var Project = ui.rowData.Project;
                                var Source = ui.rowData.Source;
                                var link = "";
                                if (doesNotContainUnassigned(Project)) {

                                    link = "<span onClick=javascript:OpenProjWindow(" + "'" + ActivityID + "','" + Project + "','Projections','" + Source + "') style='cursor: pointer;'>"
                                        + formattedAmount +
                                        "</span>";
                                }
                                else {
                                    link = "<span onClick=javascript:OpenProjWindow(" + "'" + ActivityID + "','','Projections','" + Source + "') style='cursor: pointer;'>"
                                        + formattedAmount +
                                        "</span>";
                                }
                                return link;
                                return formattedAmount;
                            } catch (error) {
                                // Code to handle the error
                                console.log('An error occurred:', error.message);
                                return "";
                            }

                        }
                    }
                ]
            },
            { dataIndx: "TPS", title: 'Total<br>Projections<br>Spent', halign: "center", valign: "top", format: '$ #,###,###.00', editable: false, summary: { type: "sum" }, valign: "top", align: "right", minWidth: 90 },
            { dataIndx: "PA", title: 'Projections<br>Available', halign: "center", valign: "top", format: '$ #,###,###.00', editable: false, summary: { type: "sum" }, valign: "top", align: "right", minWidth: 90 },
            {
                dataIndx: "curMonAct", title: '@curMonthName<br>Actual', halign: "center", valign: "top", format: '$ #,###,###.00', style: "background-color: lightyellow;",
                editable: false, summary: { type: "sum" }, valign: "top", align: "right", minWidth: 100, format: '$ #,###,###.00',
                render: function (ui) {
                    try {
                        const formattedAmount = new Intl.NumberFormat('en-US'
                            , { style: 'currency', currency: 'USD' }).format(ui.cellData); //format to USD
                        var ActivityID = ui.rowData.ActivityId;
                        var Project = ui.rowData.Project;
                        var Source = ui.rowData.Source;
                        var link = "";
                        if (doesNotContainUnassigned(Project)) {

                            link = "<span onClick=javascript:OpenTranWindow(" + "'" + ActivityID + "','" + Project + "','Current','" + Source + "') style='cursor: pointer;'>"
                                + formattedAmount +
                                "</span>";
                        }
                        else {
                            link = "<span onClick=javascript:OpenTranWindow(" + "'" + ActivityID + "','','Current','" + Source + "') style='cursor: pointer;'>"
                                + formattedAmount +
                                "</span>";
                        }
                        return link;
                    } catch (error) {
                        // Code to handle the error
                        //console.error('An error occurred:', error.message);
                        return "";
                    }

                }
            }
        ],
        hoverMode: 'cell',
        editor: { select: true, type: 'textbox' },
        trackModel: { on: true },                      //to turn on the track changes.
        editable: true,
        change: function (evt, ui) {
            //saveChanges can also be called from change event.
            var gridChanges = ui.updateList;

            $.ajax({
                url: '/APS/Activity/updatecell',         //for ASP.NET
                data: {
                    list: JSON.stringify(gridChanges)
                },
                dataType: "json",
                type: "POST",
                async: true,
                beforeSend: function (jqXHR, settings) {
                    grid3.option("strLoading", "Saving CCI Projection update, please stand by..");
                    grid3.showLoading();
                },
                success: function (changes) {
                    //commit the changes.
                    grid3.commit({ type: 'update', rows: changes.updateList });
                },
                complete: function () {
                    grid3.hideLoading();
                    $("#grids").pqGrid("refreshDataAndView");

                    grid3.option("strLoading", $.paramquery.pqGrid.defaults.strLoading);
                    grid3.refreshDataAndView();
                }
            });

        },
        destroy: function () {
            //clear the interval upon destroy.
            clearInterval(interval1);
        },
        history: function (evt, ui) {
            var $tb = this.toolbar(),
                $undo = $tb.find("button:contains('Undo')"),
                $redo = $tb.find("button:contains('Redo')");

            if (ui.canUndo != null) {
                $undo.button("option", { disabled: !ui.canUndo });
            }
            if (ui.canRedo != null) {
                $redo.button("option", "disabled", !ui.canRedo);
            }
            $undo.button("option", { label: 'Undo (' + ui.num_undo + ')' });
            $redo.button("option", { label: 'Redo (' + ui.num_redo + ')' });
        },
        groupModel: {
            on: true,                  //grouping mode.
            pivot: false,                //pivotMode
            checkbox: false,
            checkboxHead: true,
            select: false,
            titleIndx: 'grp',             //v7.0.0: new option instead of titleInFirstCol
            indent: 20,
            fixCols: false,
            groupCols: ['Region'],          //grouping along column axis.
            header: false,                //hide grouping toolbar.
            grandSummary: true,          //show grand summary row.
            dataIndx: ['ActivityId'],       //grouping along row axis.
            collapsed: [false],
            useLabel: true,
            summaryEdit: false
        },
        summaryTitle: {
            sum: ""
        },
        postRenderInterval: -1,     //synchronous post render.
        showTitle: false,
        wrap: false,
        hwrap: false,

        toolPanel: {
            show: false             //show toolPanel initially.
        },

        formulas: [
            //["TP", function (rd) {
            //    var tot = eval(Number(rd.Month1) + Number(rd.Month2) + Number(rd.Month3) + Number(rd.Month4) + Number(rd.Month5) + Number(rd.Month6) + Number(rd.Month7) + Number(rd.Month8) + Number(rd.Month9) + Number(rd.Month10) + Number(rd.Month11) + Number(rd.Month12));
            //    return tot;
            //}],
            ["RegVariance", function (rd) {
                var tot = eval(Number(rd.RegTotal) + Number(rd.ActualYTD));
                var variance = eval(Number(rd.RegBudget) - tot);
                return variance;
            }]
        ],
        toolbar: {
            items: [
                {
                    type: 'textbox',
                    label: "Filter: ",
                    attr: 'placeholder="Enter text"',
                    listener: {
                        timeout: function (evt) {
                            var txt = $(evt.target).val();
                            var rules = this.getCMPrimary().map(function (col) {
                                return {
                                    dataIndx: col.dataIndx,
                                    condition: 'contain',
                                    value: txt
                                }
                            })
                            this.filter({
                                mode: 'OR',
                                rules: rules
                            })
                        }
                    }
                },
                {
                    type: 'select',
                    label: 'Export By: ',
                    cls: 'export-format',
                    //options: [{ xlsx: 'Excel', htm: 'Html', pdf: 'PDF', csv: 'Csv' }]
                    options: [{ csv: 'Excel', htm: 'Html' }]
                },
                {
                    type: 'button',
                    label: "Export&nbsp;&nbsp;",
                    icon: 'ui-icon-arrowthickstop-1-s',
                    listener: function () {
                        var grid = this,
                            format = grid.toolbar().find('.export-format').val(),
                            data = grid.exportData({
                                format: format,
                                cssTable: 'border-spacing:0;border-collapse:separate;',
                                cssRules: "td{border:0;}",
                                render: true
                            });

                        // Strip HTML from CSV output (the "Excel" option returns CSV)
                        if (format == 'csv' && typeof data === 'string') {
                            data = stripHtmlFromCsv(data);
                        }

                        if (format == 'pdf') {
                            var dd = {
                                footer: function (currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; },
                                pageOrientation: 'landscape',
                                content: [
                                    {
                                        table: data,
                                        layout: {
                                            hLineColor: '#aaaaaa',
                                            vLineColor: '#aaaaaa'
                                        }
                                    }
                                ]
                            };
                            grid.showLoading();
                            pq.getScripts(['/Scripts/pdfmake/pdfmake.min.js', '/Scripts/pdfmake/vfs_fonts.js'], function () {
                                grid.hideLoading();
                                pdfMake.createPdf(dd).download();
                            })
                        }
                        else {
                            pq.saveAs(data, "pqGrid." + format);
                        }
                    }
                }             
            ]
        },
        //use pivotCM event to make grouped columns collapsible.
        pivotCM: function (evt, ui) {
            //add collapsible to grouped parent columns.
            this.Columns().each(function (col) {
                var cm = col.colModel
                if (cm && cm.length > 1 && !col.collapsible)
                    col.collapsible = { on: true, last: true };
            }, ui.CM);
        }
    };
    var grid3 = pq.grid("#indActivity", obj);

    grid3.option("selectionModel", { type: 'row', mode: 'single' });


...and I would like to have a tooltip popup on the Group level field, ActivityId
            { dataIndx: 'grp', title: 'ActivityId', tpHide: true, editable: false, menuInHide: true, minWidth: 150 },
            { dataIndx: "ActivityId", title: "FAS Activity", editable: false, hidden: true, filter: { groupIndx: 'Region' } },

I would like the dataIndx column, ActivityDescription, to be the source of this tooltip popup whenever I hover over the ActivityID column.  How do I program that??

25
Please use this fix and let me know the result

Code: [Select]
jQuery.paramquery.cKeyNav.prototype.resetFocusMgr=function(t,e={},n,a){var i,r=t.children(),d={textbox:"input",textarea:"textarea",contenteditable:"div[contentEditable]"}[e.type]||"textarea",o=e.attr||"";return i=r,(!("div[contentEditable]"==d?i.is("div")&&"true"==i.prop("contentEditable"):i.is(d))||1!=r.length||o)&&(t.html({input:"<input "+o+(o.includes("type")?"":" type='text'")+"/>",textarea:"<textarea "+o+"></textarea>","div[contentEditable]":"<div contenteditable='true' tabindex='0' "+o+"></div>"}[d]),r=t.children()),n&&!("ontouchstart"in window)||r.attr(r.is("div")?{contenteditable:!1}:{readonly:!0}),t[0].className="pq-focus-mgr ui-widget-content",r};
26
Yes, this issue is occurring on a live production site, so a quick fix is required.
I will continue monitoring this thread.

Please share the updated code once the fix is completed.
Thank you.
27
The fix to the issue is not available yet.
28
If the issue has been resolved, could you share the updated source code?
29
Help for ParamQuery Pro / Re: Date column filter with lte, equal or gte
« Last post by paramvir on April 21, 2026, 07:14:52 pm »
    To handle date filtering while maintaining UTC data, a more streamlined approach is to use a
Formula Column with a getter/setter rather than overriding multiple individual properties.

Recommended Approach: Two-Way Column Dependency

Instead of applying manual customizations to column.render and column.filter.conditions for every logic check, you can set up a dependency between a visible "Local" column and a hidden "UTC" column.

  • How it works: The visible column uses a get function to translate the hidden UTC data into a local format for both display and filtering. If editing is required, a set function translates the value back to UTC.
  • Result: This allows the grid's native filtering to work on local date strings without complex custom logic.


Key Resources

30
Help for ParamQuery Pro / Date column filter with lte, equal or gte
« Last post by jplevene on April 20, 2026, 10:01:52 pm »
I want to add a filter for a date column with lte, equal or gte options for the date selected in the datepicker.

  • The filter is only for the date (not the time) and each cell is formatted "YYYY-MM-DD hh:mm:ss" and is UTC.
  • Each cell has a render that converts the UTC to local so it is displayed in the local format and timezone in the cell (data is still UTC)
  • The filter is to work only on the date part, being lte, equal OR gte (ignore the time part)
  • The date picker is obviously local format and timezone
  • I also use moment (see examples below)

Basically I need to have a datepicker in the column filter, limited to a choice of lte, equal or gte and the date chosen in the drop down fileter needs to be converted to UTC before compare to the data (I could even include the time at start and end of the day for the compare so it could be a simple string compare)


I use moment so I can convert a local date to UTC by:
as_utc = moment(local_date).utc();
startUtc = moment(local_date).startOf('day').utc().format("YYYY-MM-DD HH:mm:ss");
endUtc = moment(local_date).endOf('day').utc().format("YYYY-MM-DD HH:mm:ss");
etc...


Pages: 1 2 [3] 4 5 ... 10