How to use native date picker in both form and row editing in free jqgrid
Asked Answered
H

1

1

Browser native datepicker is used for inline row editing as described in How to use input type='date' for date column in jqGrid

How to use it for form editing also? I tried code below:

  • Selected row in grid
  • Pressed edit button in toolbar
  • Pressed save button in edit form

After that date disappears from grid invdate column. Also pressing next and previous record buttons in edit form cause invdate to disappear.

How to edit and show date in edit form using browser native html5 date type picker if it is supported in browser ?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>https://mcmap.net/q/430367/-how-to-use-input-type-39-date-39-for-date-column-in-jqgrid/315935</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="author" content="Oleg Kiriljuk"/>
    <link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.11.4/themes/redmond/jquery-ui.css"/>
    <link rel="stylesheet" type="text/css" href="http://cdn.jsdelivr.net/free-jqgrid/4.8.0/css/ui.jqgrid.css"/>
    <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
    <style type="text/css">
        html, body { font-size: 75%; }
    </style>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
    <script type="text/javascript" src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
    <script type="text/javascript" src="http://cdn.jsdelivr.net/free-jqgrid/4.8.0/js/i18n/grid.locale-en.js"></script>
    <script type="text/javascript">
        $.jgrid = $.jgrid || {};
        $.jgrid.no_legacy_api = true;
        $.jgrid.useJSON = true;
    </script>
    <script type="text/javascript" src="http://cdn.jsdelivr.net/free-jqgrid/4.8.0/js/jquery.jqgrid.src.js"></script>
    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
    <script type="text/javascript">
    //<![CDATA[
        /*global $,Modernizr */
        /*jslint browser: true, unparam: true */
        $(function () {
            "use strict";
            var mydata = [
                    { id: "10",  invdate: "", name: "test1",  note: "note1",  amount: "200.00", tax: "10.00", closed: true,  ship_via: "TN", total: "210.00" },
                    { id: "20",  invdate: "2007-10-02", name: "test2",  note: "note2",  amount: "300.00", tax: "20.00", closed: false, ship_via: "FE", total: "320.00" },
                    { id: "30",  invdate: "2007-09-01", name: "test3",  note: "note3",  amount: "400.00", tax: "30.00", closed: false, ship_via: "FE", total: "430.00" },
                    { id: "40",  invdate: "2007-10-04", name: "test4",  note: "note4",  amount: "200.00", tax: "10.00", closed: true,  ship_via: "TN", total: "210.00" },
                    { id: "50",  invdate: "2007-10-31", name: "test5",  note: "note5",  amount: "300.00", tax: "20.00", closed: false, ship_via: "FE", total: "320.00" }
                ],
                $grid = $("#list"),
                initDateEdit = function (elem, options) {
                    // we need get the value before changing the type
                    var orgValue = $(elem).val(), newformat,
                        cm = $(this).jqGrid("getColProp", options.name);

                    $(elem).attr("type", "date");
                    if ((Modernizr && !Modernizr.inputtypes.date) || $(elem).prop("type") !== "date") {
                        // if type="date" is not supported call jQuery UI datepicker
                        $(elem).css({ width: "8em" }).datepicker({
                            dateFormat: "mm/dd/yy",
                            autoSize: true,
                            changeYear: true,
                            changeMonth: true,
                            showButtonPanel: true,
                            showWeek: true
                        });
                    } else {
                        // convert date to ISO
                        if (orgValue !== "") {
                            newformat = cm.formatoptions != null && cm.formatoptions.newformat ?
                                cm.formatoptions.newformat :
                                $(this).jqGrid("getGridRes", "formatter.date.newformat");
                            $(elem).val($.jgrid.parseDate.call(this, newformat, orgValue, "Y-m-d"));
                        }
                        // "10em" is better for Chrome and "11em" for Opera 24
                        $(elem).css("width", /OPR/.test(navigator.userAgent) ? "11em" : "10em");
                    }
                },
                myBeforeSaveRow = function (options, rowid) {
                    var $self = $(this), $dates = $("#" + $.jgrid.jqID(rowid)).find("input[type=date]");
                    $dates.each(function () {
                        var $this = $(this), newformat, str,
                            id = $this.attr("id"),
                            colName = id.substr(rowid.length + 1),
                            cm = $self.jqGrid("getColProp", colName);
                        if ((Modernizr && Modernizr.inputtypes.date) || $this.prop("type") === "date") {
                            // convert from iso to newformat
                            str = $this.val();
                            if (str !== "") {
                                newformat = cm.formatoptions != null && cm.formatoptions.newformat ?
                                    cm.formatoptions.newformat :
                                    $self.jqGrid("getGridRes", "formatter.date.newformat");
                                str = $.jgrid.parseDate.call($self[0], "Y-m-d", str, newformat);
                            }
                            $this.attr("type", "text");
                            $this.val(str);
                        }
                    });
                },
                initDateSearch = function (elem) {
                    setTimeout(function () {
                        $(elem).datepicker({
                            dateFormat: "mm/dd/yy",
                            autoSize: true,
                            changeYear: true,
                            changeMonth: true,
                            showWeek: true,
                            showButtonPanel: true
                        });
                    }, 50);
                },
                numberTemplate = {formatter: "number", align: "right", sorttype: "number",
                    editrules: {number: true, required: true},
                    searchoptions: { sopt: ["eq", "ne", "lt", "le", "gt", "ge", "nu", "nn", "in", "ni"] }};

            $grid.jqGrid({
                datatype: "local",
//loadComplete: function() {
//    $grid.jqGrid('setGridParam', { datatype: 'json' });
//},
                data: mydata,
                colNames: ["Client", "Date", "Closed", "Shipped via", "Notes", "Tax", "Amount", "Total"],
                colModel: [
                    { name: "name", align: "center", editable: true, width: 65, editrules: {required: true} },
                    { name: "invdate", width: 125, align: "center", sorttype: "date",
                        formatter: "date", /*formatoptions: { newformat: "m/d/Y"},*/ editable: true,
                        editoptions: { dataInit: initDateEdit },
                        searchoptions: { sopt: ["eq", "ne", "lt", "le", "gt", "ge"], dataInit: initDateSearch } },
                    { name: "closed", width: 70, align: "center", editable: true, formatter: "checkbox",
                        edittype: "checkbox", editoptions: {value: "Yes:No", defaultValue: "Yes"},
                        stype: "select", searchoptions: { sopt: ["eq", "ne"], value: ":Any;true:Yes;false:No" } },
                    { name: "ship_via", width: 105, align: "center", editable: true, formatter: "select",
                        edittype: "select", editoptions: { value: "FE:FedEx;TN:TNT;IN:Intim", defaultValue: "IN" },
                        stype: "select", searchoptions: { sopt: ["eq", "ne"], value: ":Any;FE:FedEx;TN:TNT;IN:IN" } },
                    { name: "note", width: 60, sortable: false, editable: true, edittype: "textarea" },
                    { name: "tax", width: 52, editable: true, template: numberTemplate },
                    { name: "amount", width: 75, editable: true, template: numberTemplate },
                    { name: "total", width: 60, template: numberTemplate }
                ],
                rowNum: 10,
                rowList: [5, 10, 20],
                iconSet: "fontAwesome",
                pager: "#pager",
                gridview: true,
                autoencode: true,
                ignoreCase: true,
                sortname: "invdate",
                viewrecords: true,
                sortorder: "desc",
                height: "auto",
                rownumbers: true,
                editurl: "clientArray",
//editurl: "http://cdn.jsdelivr.net/test",
        toppager: true,

                onSelectRow: function (rowid) {
                    var $self = $(this),
                        savedRow = $self.jqGrid("getGridParam", "savedRow");
                    if (savedRow.length > 0) {
                        $self.jqGrid("restoreRow", savedRow[0].id);
                    }
                    $self.jqGrid("editRow", rowid, {
                        keys: true,
                        beforeSaveRow: myBeforeSaveRow
                    });
                }
            });

    $.extend(true,$.jgrid.edit, {
        closeAfterAdd: true,
        navkeys: [true,33,34],
        savekey: [true, 13],
        recreateForm: true,
        reloadAfterSubmit: false,
        left: 10,
        top: 15,
        dataheight: '100%',
        width: window.innerWidth - 18
    });



        $grid.jqGrid("navGrid", "#list_toppager", {
edit: true
});

        });
    //]]>
    </script>
</head>
<body>
    <table id="list"><tr><td></td></tr></table>
    <div id="pager"></div>
</body>
</html>
Heid answered 22/3, 2015 at 12:32 Comment(0)
M
1

The workaround used in myBeforeSaveRow need be implemented in form editing too. Instead of that I changed the code of free jqGrid so that you **don't need to use beforeSaveRow: myBeforeSaveRow at all. I adjusted the code of inline editing and form editing so that it works correctly on saving the data from <input type="date">. One should be only careful and set the value of type to text if type="date" is not supported.

The demo uses the current code of free jqGrid from GitHub. I tested the demo in Chrome 41, Opera 28 where <input type="date"> is supported. I tested the changes in Safari 5.1.7, Firefox 37 and IE 10. The demo works here too. It use the following modified code of initDateEdit:

var initDateEdit = function (elem, options) {
    // we need get the value before changing the type
    var orgValue = $(elem).val(), newformat,
        cm = $(this).jqGrid("getColProp", options.name);

    $(elem).attr("type", "date");
    if ((typeof Modernizr !== "undefined" && !Modernizr.inputtypes.date) || $(elem).prop("type") !== "date") {
        $(elem).attr("type", "text"); // !!! important to make saving works correctly
        $(elem).css({ width: "8em" }).datepicker({
            dateFormat: "mm/dd/yy",
            autoSize: true,
            changeYear: true,
            changeMonth: true,
            showButtonPanel: true,
            showWeek: true
        });
    } else {
        // convert date to ISO
        if (orgValue !== "") {
            newformat = cm.formatoptions != null && cm.formatoptions.newformat ?
                cm.formatoptions.newformat :
                $(this).jqGrid("getGridRes", "formatter.date.newformat");
            $(elem).val($.jgrid.parseDate.call(this, newformat, orgValue, "Y-m-d"));
        }
        $(elem).css({width: "11em"});
    }
};

The other code of inline and form editing is the standard:

    ...
    onSelectRow: function (rowid) {
        var $self = $(this),
            savedRow = $self.jqGrid("getGridParam", "savedRow");
        if (savedRow.length > 0 && savedRow[0].id !== rowid) {
            $self.jqGrid("restoreRow", savedRow[0].id);
        }
        $self.jqGrid("editRow", rowid);
    },
    inlineEditing: {
        keys: true
    }
}).jqGrid("navGrid").jqGrid("inlineNav");

The options beforeSaveRow: myBeforeSaveRow are removed.

Microspore answered 22/3, 2015 at 18:10 Comment(8)
initDateSearch does not use native DatePicker. How to use it for search also ?Heid
if Modernizer is not included, this code causes javascript exception. How to use it without Modernizer ?Heid
pressing next and previous record buttons in form editing still shows empty date. If date is empty, pressing next button in form editing also fills date in gridHeid
@Andrus: I don't want to write here full implementation of <input type="data"> in all cases. You question was: "How to use native date picker in both form and row editing in free jqGrid". Form editing had a real problem which is fixed now. The test for existence Modernizr can be easy changed to typeof Modernizr !== "undefined". I included viewPagerButtons: false option in form editing. If you want you can include afterclickPgButtons callback which fill editing filed of <input type="date"> correctly.Microspore
I deleted date in form editing in last demo and pressed submit button. Date at year 1970 appears in grid instead of empty date.Heid
@Andrus: I made one more small modification of the code. Now it's possible to save empty date in form editing like it's possible in inline editing too. The demo from the answer uses the new code and it works now.Microspore
If bootstrap is used, date increment and decrement spinner appears in wrong place, out of line in Chrome. Clicking in spinner changes value continuously. How to make it bootstrap compatible ?Heid
@Andrus: You can fix the problem by fixing line-height. For example .ui-jqgrid td input[type=date], input[type=time], input[type=datetime-local], input[type=month] { line-height: normal; }. See the demo. I think it's better to post the information in new question to make other to find problem and the solution.Microspore

© 2022 - 2024 — McMap. All rights reserved.