How to use input type='date' for date colu

2020-02-06 13:49发布

问题:

jqGrid date column for inline editing is defined using colmodel and javascript below.

It uses jquery ui-date picker. This is lot of code to maintain and result is ugly.

How to use html5 native input type='date' for inline date editing if this is supported by browser instead of this code ?

colmodel:

{"template":DateTemplate
,"label":"Invoice date",
"name":"Invoicedate",
"index":"Invoicedate",
"editoptions":{
  "dataInit":initDateWithButton
  ,"size":10
  },

"searchoptions":{"dataInit":initDateWithButton
,"size":10,"attr":{"size":10}},"width":50
}

javascript:

var DateTemplate = {
    sorttype: 'date', formatter: 'date',
    formatoptions: {
        srcformat: "Y-m-d"
    },

    editoptions: { maxlength: 10, size: 10, dataInit: initDateWithButton },
    editable: true,
    searchoptions: {
        sopt: ['eq', 'ne', 'lt', 'le', 'gt', 'ge'],
        dataInit: initDateWithButton,
        size: 11,          // for the advanced searching dialog 
        attr: { size: 11 }   // for the searching toolbar 
    }
};

var initDateWithButton = function (elem) {
    if (/^\d+%$/.test(elem.style.width)) {
        // remove % from the searching toolbar 
        elem.style.width = '';
    }
    // to be able to use 'showOn' option of datepicker in advance searching dialog 
    // or in the editing we have to use setTimeout 
    setTimeout(function () {
        $(elem).css({ "box-sizing": "border-box", width: "5.7em" }).datepicker({
            // dateFormat: 'dd.mm.yy',
            showOn: 'button',
            changeYear: true,
            changeMonth: true,
            showWeek: true,
            showButtonPanel: true,
            onClose: function (dateText, inst) {
                inst.input.focus();
            }
        })
            .removeClass("ui-corner-all").addClass("ui-corner-left");

        $(elem).next('button.ui-datepicker-trigger').button({
            text: false,
            icons: { primary: 'ui-icon-calendar' }
        }).css({ width: '1em', height: '1.09em' })
            .removeClass("ui-corner-all").addClass("ui-corner-right")
        .find('span.ui-button-text')
        .css({ padding: '0.1em' })
        .siblings('span.ui-button-icon-primary')
        .css({ marginLeft: "-8.5px", marginTop: "-8.5px" });
        $(elem).next('button.ui-datepicker-trigger').andSelf().css("verticalAlign", "middle");
    }, 100);
};

This is ASP.NET MVC4 application.

Update

I tried answer but got issues.

  1. Date template in question does not contain newformat so this is still not defined. I replaced date parsing line with line

    $(elem).val($.jgrid.parseDate($.jgrid.formatter.date.newformat, orgValue, "Y-m-d"));
    

as recommended in comment.

  1. Line str = $.jgrid.parseDate("Y-m-d", $this.val(), cm.formatoptions.newformat);

convets valid date which is already converted to iso, like 1973-02-15 to long format like Thu Feb 15 1973 00:00:00 GMT+0200 (FLE Standard Time)

Required result is 1973-02-15 so conversion is not needed.

I solved this by replacing line

$this.val(str);

with

$this.val($this.val());

  1. After date inline edit is finished, date is shown in column in iso format. Localized date is shown only after grid is refreshed.

** Update **

Date does not fit to column width. In IE button is visible:

but in Chrome for same column width big empty space appears and only part of first button is visible:

How to fix this so that buttons are visible for same column width ?

回答1:

I find your question interesting and created the demo which works in Google Chrome without jQuery UI Datepicker and display during date editing the results like

The demo have column invdate defined as below

{ name: "invdate", width: 120, align: "center", sorttype: "date",
    formatter: "date", formatoptions: { newformat: "m/d/Y"}, editable: true,
    editoptions: { dataInit: initDateEdit } }

The callback function initDateEdit I defined as

var initDateEdit = function (elem, options) {
    // we need get the value before changing the type
    var orgValue = $(elem).val(),
        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).datepicker({
            dateFormat: "mm/dd/yy",
            autoSize: true,
            changeYear: true,
            changeMonth: true,
            showButtonPanel: true,
            showWeek: true
        });
    } else {
        // convert date to ISO
        $(elem).val($.jgrid.parseDate.call(this, cm.formatoptions.newformat, orgValue, "Y-m-d"));
    }
};

I don't know <input type="date"/> good enough. It uses input format of date as ISO. So I converted in the code above the original text to ISO to display correct date during editing. In the same way one have to convert the results of editing back to the formatoptions.newformat. I used beforeSaveRow callback in the case:

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, {
        keys: true,
        beforeSaveRow: myBeforeSaveRow
    });
}

where myBeforeSaveRow are defined as the following:

var myBeforeSaveRow = function (options, rowid) {
    var $self = $(this), $dates = $("#" + $.jgrid.jqID(rowid)).find("input[type=date]");
    $dates.each(function () {
        var $this = $(this),
            id = $this.attr("id"),
            colName = id.substr(rowid.length + 1),
            cm = $self.jqGrid("getColProp", colName),
            str;
        if ((Modernizr && Modernizr.inputtypes.date) || $this.prop("type") === "date") {
            // convert from iso to newformat
            str = $.jgrid.parseDate.call($this[0], "Y-m-d", $this.val(), cm.formatoptions.newformat);
            $this.attr("type", "text");
            $this.val(str);
        }
    });
};

UPDATED: One more demo supports better Opera 24 and empty input dates.

UPDATED 2: The demo contains small modification (the setting of this for $.jgrid.parseDate) and it uses free jqGrid 4.8.