Creating Custom Time Widget in GridMVC

Oct 10, 2014 at 1:15 PM
Edited Oct 10, 2014 at 1:17 PM
I am trying create Time widget to filter records by time in Grid MVC. i am able to see the control but it does not filter any records. here is the script. I have added script, view code for mvc grid and the index page as well.

Script

function TimeWidget() {

this.getAssociatedTypes = function () {
    return ["TimeFilterWidget"];
};
this.onShow = function () {
};

this.showClearFilterButton = function () {
    return true;
};

this.onRender = function (container, lang, typeName, values, cb, data) {
    //store parameters:
    this.cb = cb;
    this.container = container;
    this.lang = lang;

    //this filterwidget demo supports only 1 filter value for column column
    this.value = values.length > 0 ? values[0] : { filterType: 1, filterValue: "" };

    this.renderWidget(); //onRender filter widget
    //this.loadCustomers(); //load customer's list from the server
    this.registerEvents(); //handle events
};

this.renderWidget = function () {
    var html = '\<p>Select Time to filter:</p>\
                <p><input class="time" type="time" id="tminput"/></p>\
                ';
    this.container.append(html);
};

this.registerEvents = function () {                
    var x = document.getElementById("tminput");
    x.addEventListener("blur", myBlurFunction, true);        
};

function myBlurFunction() {
    var $context = this;
    var values = [{ filterValue: $(this).val(), filterType: 1 /* Equals */ }];        
    $context.cb(values);
}

}

View

@using GridMvc.Html
@using GridMvc.Sorting
@model IEnumerable<GridMvc.Site.Logging>

@Html.Grid(Model).Named("ordersGrid").Columns(columns =>
{
    /* Adding "OrderID" column: */

    columns.Add(o => o.ID)
           .Titled("Number")
           .SetWidth(100);
    columns.Add(o => o.DateTime, "Date")
            .Titled("Date")
            .SortInitialDirection(GridSortDirection.Descending)
            .Format("{0:dd/MM/yyyy}")
            .SetWidth(110);
    columns.Add(o => o.DateTime, "Time")
            .Titled("Time")
            .SortInitialDirection(GridSortDirection.Descending)
            .Format("{0:hh:mm tt}")                
            .SetWidth(110)
            .SetFilterWidgetType("TimeFilterWidget");
    columns.Add(o => o.Type)
           .Titled("Type")
           .SetWidth(150)
           .ThenSortByDescending(o => o.ID)
           .SetFilterWidgetType("TypeFilterWidget");
    columns.Add(o => o.Description)
           .Titled("Description")
           .SetWidth(250);
    columns.Add(o => o.Reference)
            .Titled("Reference")
            .SetWidth(150)
            .Css("hidden-xs"); //hide on phones
    columns.Add(o => o.Response)
            .Titled("Response")
            .SetWidth(150)
            .Css("hidden-xs"); //hide on phones        


}).WithPaging(15).Sortable().Filterable().WithMultipleFilters()

<script>
$(function () {
    pageGrids.ordersGrid.addFilterWidget(new TypeWidget());
    pageGrids.ordersGrid.addFilterWidget(new TimeWidget());
});
</script>
Oct 13, 2014 at 1:26 AM
Edited Oct 13, 2014 at 1:27 AM
If you want to filter by time only then you could try returning time only to a date-time field from you data source, e.g.
select cast(myDate as time) from myTable
You could have another column in the grid, for just the date, e.g.
Select  cast(myDate as date)
Then you would not need to add a filter as the Filterable() property on the grid should do the rest. I haven't tested this for a time only field but it works for a date only field.
Oct 13, 2014 at 6:06 AM
I am using c# and entity model to return list of model so below is my code. i am not sure how can i manipulate it I tried making another column as string and its simply showing me value box to filter just like text. i want the time picker to appear instead of this value box.

Controller Code

        public ActionResult Grid()
        {
            wmas_subsEntities entitymodel = new wmas_subsEntities();
            
            List<GridMvc.Models.Logging> Logs = new List<Models.Logging>();                       

            foreach(var item in entitymodel.Loggings.ToList())
            {
                Logs.Add(new Models.Logging()
                {
                    Date = item.DateTime.Value,
                    Description = item.Description,
                    ID = item.ID,
                    Reference = item.Reference,
                    Response = item.Response,
                    Time = String.Format("{0:hh:mm}", item.DateTime),                    
                    Type = item.Type
                });
            }

            return PartialView("_OrdersGrid", Logs.OrderByDescending(p => p.ID));            
        }

Model

    public partial class Logging
    {
        public int ID { get; set; }
        public string Type { get; set; }
        public string Description { get; set; }
        public DateTime Date { get; set; }
        public string Time { get; set; }
        public string Reference { get; set; }
        public string Response { get; set; }
    }
Oct 14, 2014 at 3:46 AM
Edited Oct 14, 2014 at 4:25 AM
You should try making your Time field a DateTime data type:
    public partial class Logging
    {
        public int ID { get; set; }
        public string Type { get; set; }
        public string Description { get; set; }
        public DateTime Date { get; set; }
        public DateTime Time { get; set; }
        public string Reference { get; set; }
        public string Response { get; set; }
    }
I don't understand why you made it a string in the first place but I doubt a string data type will work with the datetimepicker, it must be a datetime data type. You should set Date to a valid date and time, and also set Time to the same valid date and time.

Then see if the Format method will render the time only for the Time field. I am not sure how much formatting you can do with the datetimepicker but it should be able to render the time only if you get the format parameters correct and only format on the grid:
.Format("{0:hh:mm tt}")
Do not format in the Controller, just the grid like so:
 columns.Add(o => o.Date)
            .Titled("Date")
            .SortInitialDirection(GridSortDirection.Descending)
            .Format("{0:dd/MM/yyyy}")
            .SetWidth(110);
 columns.Add(o => o.Time)
            .Titled("Date")
            .SortInitialDirection(GridSortDirection.Descending)
            .Format("{0:hh:mm tt}")
            .SetWidth(110);
I could not however get the date filter to show time only, it still rendered dates only.

So another approach would be to make the Time field an integer and then convert to military time so you have 0000, 0100, 0200...2359. This would have to work on the filter as an integer field but I haven't tested this approach.

Then you could use the Format method on the grid and render hh:mm:ss (also consider the RenderAsValue method).
Oct 14, 2014 at 5:48 AM
I have tried every approach but it does not work with time only. it always shows calendar. i think i need to build custom filter. can you please help me how can i use time picker in custom filter ?
Oct 14, 2014 at 6:08 AM
Edited Oct 14, 2014 at 6:08 AM
mrhammad wrote:
I have tried every approach but it does not work with time only. it always shows calendar. i think i need to build custom filter. can you please help me how can i use time picker in custom filter ?
Sorry mrhammad, I have not built a customer filter yet so I can't really help with that.

However, as I said previously, a simple alternative would be to make the Time property an integer data type in the Logging class, and then in the Controller convert the time part of the date to 24hour format, then to a number, so for example 23:11 would be converted to 2311, and store it in the Time property as a 4 digit number (or 6 digit number if you want to include seconds).

You would then end up with a normal numeric filter and your grid would look something like this:
Date             Time
01/12/2013       2311
02/12/2013       0110
02/12/2013       1224
You could then filter by date and time separately.

I know this isn't what you want exactly but I think it would work just fine.