How to use DateRangePicker on C# Razor page? - c#

I'm having trouble on how to implement a date range picker on a C# Razor Page. I've seen some examples for singular date pickers (like picking one date), but not much for date ranges.
So the page I'm working on uses HTML Helpers. It gets it's properties from this class/model:
public class Appointment{
[Display(Name = "Name")]
public string Name { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
#using (Html.BeginForm(..., ..., FormMethod.Get, ...){
<div>
#Html.LabelFor(x => x.Name)
</div>
<div>
#Html.TextBoxFor(x => x.Name)
</div>
-- the date range input field would be below the above input field, but I'm confused how to use the Html Helper for the two dates for the singular daterangepicker input field
}
The JavaScript example code for the daterangepicker is from this site, and looks like this:
<script type="text/javascript">
$(function() {
var start = moment().subtract(29, 'days');
var end = moment();
function cb(start, end) {
$('#reportrange span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));
}
$('#reportrange').daterangepicker({
startDate: start,
endDate: end,
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
'Last 30 Days': [moment().subtract(29, 'days'), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')],
'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
}
}, cb);
cb(start, end);
});
</script>
Basically I'm confused on how a singular input field is going to map to both StartDate and EndDate. I see that TextBoxFor accepts one property, but not sure how you would handle more than that.

This Javascript will generate a text about the Date range, In my opinion, you can add some code to bind value to your datetime in model, Please refer to this demo.
PageModel
[BindProperty]
public Appointment appointment { get; set; }
View
<form asp-action="Privacy" method="post">
<div class="form-group">
<label asp-for="appointment.Name" class="control-label"></label>
<input asp-for="appointment.Name" class="form-control" />
</div>
<input asp-for="appointment.StartDate" type="hidden" class="form-control" />
<input asp-for="appointment.EndDate" type="hidden" class="form-control" />
<hr />
<div id="reportrange" style="background: #fff; cursor: pointer; padding: 5px 10px; border: 1px solid #ccc; width: 100%">
<i class="fa fa-calendar"></i>
<span></span> <i class="fa fa-caret-down"></i>
</div>
<button type="submit">Submit</button>
</form>
Javscript
function cb(start, end) {
$('#reportrange span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));
// add this code to bind value.
var s = start.toJSON();
var e = end.toJSON();
$('#appointment_StartDate').val(s);
$('#appointment_EndDate').val(e);
}
Demo:

Related

How to do Date validation in Razor .Net Core

Need standard validations for Start and End Dates. Should include:
End Date > Start Date.
End Date < Today Date.
Start Date < End Date
So far tried below approaches, but these do not work completely:
ASP MVC Datetime range data annotation from now to 20 years?
Please advise.
You can use fluent validation to achieve this. I write a simple demo here and hope it can help you.
Demo
public class Time
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
DateTimeValidator
public class DateTimeValidator : AbstractValidator<Time>
{
public DateTimeValidator()
{
DateTime now = DateTime.Now;
RuleFor(x => x.Start)
.LessThan(x => x.End)
.WithMessage("Start must < End")
.NotEmpty();
RuleFor(x => x.End)
.GreaterThan(x => x.Start)
.WithMessage("End must > Start")
.NotEmpty();
}
}
Page
#model Time
<form asp-action="Time" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Start" class="control-label" ></label>
<input asp-for="Start" class="form-control" type="date" max='' id="startDate"/>
<span asp-validation-for="Start" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="End" class="control-label"></label>
<input asp-for="End" class="form-control" type="date" max='' id="endDate"/>
<span asp-validation-for="End" class="text-danger"></span>
</div>
<button type="submit">submit</button>
</form>
#section Scripts{
<script>
//I use js to allow users to select only the latest date up to yesterday
function addZero(n) {
return parseInt(n) >= 10 ? n.toString() : '0' + n;
}
let dateNow = new Date(),
yearNow = dateNow.getFullYear(),
monthNow = dateNow.getMonth() + 1,
dayNow = dateNow.getDate() - 1,
maxDate = yearNow + '-' + addZero(monthNow) + '-' + addZero(dayNow);
let inp = document.querySelector('#startDate');
let inp2 = document.querySelector('#endDate');
inp.setAttribute('max', maxDate);
inp2.setAttribute('max',maxDate);
</script>
}
Demo
Edit
[HttpPost]
public IActionResult Time(Time modeo)
{
if (ModelState.IsValid)
{
// add your code here.....
}
//return model and error message
return View(modeo);
}

Bootstrap datepicker. Trouble binding: The value is not valid

I'm having trouble binding a property of my model using bootstrap datepicker. I'm getting the following error:
The value DATE is not valid for DATEFIELD
This is how the property is defined in my model:
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
public DateTime FechaDesignado { get; set; }
This is how the view is constructed:
<div class="form-group">
<div>
<input type="datetime" class="datepicker form-control" asp-for="#item.FechaDesignado"/>
<span asp-validation-for="#item.FechaDesignado" class="text-danger"></span>
</div>
</div>
Which translates to:
<div class="form-group" form="form1">
<div>
<input type="datetime" class="datepicker form-control" data-val="true" data-val-required="The FechaDesignado field is required." name="item.FechaDesignado" value="09/01/1901" />
<span class="text-danger field-validation-valid" data-valmsg-for="item.FechaDesignado" data-valmsg-replace="true"></span>
</div>
</div>
This is how it looks on my DB.
This is the code for datepicker:
<script type="text/javascript">
$(function () {
$('.datepicker').datepicker({
"autoclose": true
});
});
</script>
Post Action inside the Controller:
[HttpPost, ActionName("Management")]
//[ValidateAntiForgeryToken]
public async Task<IActionResult> Management(int? id)
{
var storetoupdate = _context.Stores.SingleOrDefault(m => m.StoreID == id.Value);
if (await TryUpdateModelAsync(
storetoupdate, "item",
s => s.StoreName, s => s.IncomePeriodicity, s=>s.Usuario, s => s.FechaDesignado))
{
await _context.SaveChangesAsync();
return RedirectToAction("Management");
}
return RedirectToAction("Management");
}
Question: Seems like I must convert the date input field to a datetime object using DateTime.ParseExact but I don't know how to edit the controller for this. Sorry but I'm learning all this.
Thanks.
You can use DateTime.ParseExact for convert date format to datetime. Please see this for more information.
Edit
You can use data-format attribute like this for post correct format date:
<input data-format="0:MM/dd/yyyy" type="datetime" class="datepicker form-control" asp-for="#item.FechaDesignado"/>

Telerik UI for MVC => DateTime bug

I am working with Telerik (Kendo) UI for ASP.NET MVC and I am using grid. The problem is that I have bug with DateTime type. Here source:
This is a part from my model:
public class Discussion
{
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime Date { get; set; }
// More code...
}
This is my editor template(which comes from Telerik UI)
#model DateTime?
<div style="background-color: red; color: aqua; font-size: 28px;">
#(Html.Kendo().DatePickerFor(m => m)
.Format("MM/dd/yyyy"))
</div>
And in view (in grid) this is for date property:
columns.Bound(model => model.Date).Width(150).Format("{0:MM/dd/yyyy}");
The problem is that after I create new element => http://prntscr.com/8iq7si
in my controller I receive date with value: {1.1.0001 г. 0:00:00} => http://prntscr.com/8iq8eq
In very rare cases the date is send, but than there is some bug with format and ModelState is never valid.
P.S Here what is generated html:
<input data-val="true" data-val-date="The field Date must be a date." data-val-required="The Date field is required." id="Date" name="Date" type="text" value="01.01.0001" data-role="datepicker" class="k-input" role="combobox" aria-expanded="false" aria-owns="Date_dateview" aria-disabled="false" aria-readonly="false" data-bind="value:Date" style="width: 100%;">

Binding my view model to a view causes all check boxes to be checked

I'm having an issue where my all the check boxes rendered in the view are coming out checked. I put a breakpoint at the line where my view model is constructed and through the debugger, I can see that some values are set to "true" and others are set to "false". So the problem, I'm assuming, has got to be in the view itself.
Here is my model:
public class UserModulesAdministrationViewModel
{
public bool AccessGranted { get; set; }
public int ModuleId { get; set; }
public string ModuleName { get; set; }
public string ModuleDescription { get; set; }
}
Here is my controller that is rendering the list:
public ActionResult UserModules(int id)
{
// Database stuff here
var model = modules.Select(module => new Infrastructure.ViewModels.UserModulesAdministrationViewModel
{
ModuleId = module.AccessModuleId,
AccessGranted = userModules.Any(z => z.AccessModuleId == module.AccessModuleId),
ModuleName = module.ModuleName,
ModuleDescription = module.ModuleDescription
}).ToList();
return View(model);
}
And finally here is my relevant view code:
#model IEnumerable<UserModulesAdministrationViewModel>
#foreach (UserModulesAdministrationViewModel m in Model)
{
<div class="col-md-4" style="margin-top: 15px;">
<div class="moduleBlockLong" style="position: relative">
<div class="moduleHeader">#m.ModuleName</div>
<div class="moduleText">#m.ModuleDescription</div>
<div class="checkbox" style="position: absolute; bottom: 0; right: 80px">
<label>
#{
var m1 = m;
}
#Html.CheckBoxFor(z => m1.AccessGranted )
<input type="checkbox" value="" checked="checked"/> Allow Access
</label>
</div>
</div>
</div>
}
The problem seems to me like you have hardcoded the input after the CheckBoxFor HtmlHelper.
#Html.CheckBoxFor(z => m1.AccessGranted )
<input type="checkbox" value="" checked="checked"/>
Remove:
<input type="checkbox" value="" checked="checked"/>
It's also worth noting that as you are using a foreach loop rather than a for loop that you will not be able to post the selected values back to the server.
You will need to index your loop as follows:
#for (var i = 0; i < Model.Count; i++)
{
// code
#Html.CheckBoxFor(z => Model[i].AccessGranted)
// rest of code
}
Or you will not be able to read any user input on the server.
In your view, remove
<input type="checkbox" value="" checked="checked"/> Allow Access
Because of checked="checked", this will always print out a checked checkbox.
I think that happens because you left <input type="checkbox" value="" checked="checked"/>
Remove it and it will works.
Also there exist another problem about foreach loop.
ASP.NET MVC 4 - for loop posts model collection properties but foreach does not
Solution:
#for(var i = 0; i<Model.Count; i++)
{
<div class="col-md-4" style="margin-top: 15px;">
<div class="moduleBlockLong" style="position: relative">
<div class="moduleHeader">#Model[i].ModuleName</div>
<div class="moduleText">#Model[i].ModuleDescription</div>
<div class="checkbox" style="position: absolute; bottom: 0; right: 80px">
<label>
#Html.CheckBoxFor(z => Model[i].AccessGranted) Allow Access
</label>
</div>
</div>
</div>
}
Try this code...
Instead of : <input type="checkbox" value="" checked="checked"/> Allow Access
Try:
<input type="checkbox" value="" checked="#m.AccessGranted "/> Allow Access
In addition, don't use m1 parameter..

How to hide one field when the user enter data in another field .NET MVC 4 Razor

I had one field something like Holiday such that is given below,
[StringLength(50)]
[DisplayName(Constants.DisplayName.HolidayDay)]
public virtual string HolidayDay { get; set; }
And
public virtual enumHolidayDay enumHolidayDay
{
get
{
return (enumHolidayDay)Enum.Parse(typeof(enumHolidayDay), HolidayDay);
}
set
{
HolidayDay = value.ToString();
}
}
And
public enum enumHolidayDay
{
[Description("Saturday")]
saturday = 1,
[Description("Sunday")]
sunday = 2,
}
And my Holiday.cshtml file is following
<div class="row">
<div class="col-md-3">
<label for="" class="control-label">
Set Holiday For </label><br />
#Html.EnumCheckBoxFor(m => m.enumHolidayDay)
</div>
</div>
<br/>
<div class="row">
<div class="col-md-3">
<label for="" class="control-label">
Day</label><br />
#Html.TextBoxFor(model => model.HolidayDay, new { #class = "form-control"
}).DisableIf(() => Model.IsReadOnly == true)
</div>
</div>
On my screen there are two checkboxes named Saturday and another one is Sunday. And one textbox named Day, But user can enter data in either one of it. One is mandatory. How to handle them, i.e. How to disable the Day field when the user click the any checkbox. And the Holiday field only used to these controls. In which event i have to handle it without using scripts and what are the code i need to add for this. Can anyone please help to find the solution...
Check bellow code
With jQUery
$('#checkboxId').click(function () {
$("#txtholidy").toggle(!this.checked);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type='checkbox' id="checkboxId" checked='checked'>Sunday
</br></br><input type='textbox' id="txtholidy" style='display:none' >
Updated
Without jQUery
function toggleControl()
{
if(document.getElementById("checkboxId").checked == true)
{
document.getElementById("txtholidy").style.visibility="hidden";
}
else
{
document.getElementById("txtholidy").style.visibility="visible";
}
}
<input type='checkbox' id="checkboxId" checked='checked' onClick="toggleControl()">Sunday
</br></br><input type='textbox' id="txtholidy" style="visibility:hidden" >

Categories