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://stackoverflow.com/q/26040738/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>
Community
  • 1
  • 1
Andrus
  • 26,339
  • 60
  • 204
  • 378

1 Answers1

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.

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • initDateSearch does not use native DatePicker. How to use it for search also ? – Andrus Mar 22 '15 at 19:13
  • if Modernizer is not included, this code causes javascript exception. How to use it without Modernizer ? – Andrus Mar 22 '15 at 19:16
  • 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 grid – Andrus Mar 22 '15 at 19:24
  • @Andrus: I don't want to write here full implementation of `` 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 `` correctly. – Oleg Mar 22 '15 at 19:47
  • I deleted date in form editing in last demo and pressed submit button. Date at year 1970 appears in grid instead of empty date. – Andrus Mar 22 '15 at 19:55
  • @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. – Oleg Mar 22 '15 at 20:23
  • 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 ? – Andrus Mar 28 '15 at 20:00
  • @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](http://www.ok-soft-gmbh.com/jqGrid/OK/dateInput_48_bootstrap.htm). I think it's better to post the information in new question to make other to find problem and the solution. – Oleg Mar 28 '15 at 20:29