I have a list of dates that I want to disable in my bootstrap date picker. I cannot get the datesDisabled function to work with the array of dates returned from JSON. It does work with a hard coded array of dates.
Is there something that I need to do format the dates returned from JSON in order to get it to work?
Query:
var DatesBooked= JsonConvert.SerializeObject(db.Calendar.Where(x => x.CalLocation != "OFF")).Select(x => x.CalDate).Distinct().ToList());
In my view:
#Html.TextBox("AddedDates", null, new { #class = "form-control small", #Value = ViewBag.SelDate, autocomplete = "off" })
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script src="~/Scripts/jquery.timepicker.js"></script>
<script src="~/Scripts/bootstrap-datepicker.min.js"></script>
<script>
var unavailableDates= #Html.Raw(Json.Encode(Model.DatesBooked));
$input = $("#AddedDates");
$input.datepicker({
multidate: true,
multidateSeparator: ',',
datesDisabled: unavailableDates,
});
</script>
unavailableDates value
var unavailableDates = "[\"2016-05-01T00:00:00\",\"2016-05-02T00:00:00\",\"2016-05-03T00:00:00\",\"2016-06-24T00:00:00\",\"2016-06-25T00:00:00\"]"
If I hardcode thisfor unavailableDates, everything works fine.
var unavailableDates = ["05/25/2016", "05/26/2016"]
How do I need to format the dates in order to get this to work?
TIA!
Well after many attempts and more research, I was able to solve this by doing the following:
I reformatted the date using C#:
var checkdates = db.Calendar.Where(x => x.CalLocation != "OFF")).Select(x => x.CalDate).Distinct().ToList()
var DatesBooked= JsonConvert.SerializeObject(checkdates, Formatting.None, new IsoDateTimeConverter() { DateTimeFormat = "MM/dd/yyyy" });
Then in the view, I stripped the "\" characters returned by JSON and created an array:
var unavailableDates = #Html.Raw(Json.Encode(Model.DatesBooked));
var formatDates = unavailableDates.replace(/\\/g, "");
var trimDate = formatDates.slice(1, -1); // to remove " at beginning and end
var finalDates = JSON.parse("[" + trimDate + "]");
$input = $("#AddedDates");
$input.datepicker({
multidate: true,
multidateSeparator: ',',
datesDisabled: finalDates,
todayHighlight: true
});
Related
I'm using Fullcalendar to render a calendar.
Everything is working fine, but I have a specific request that I've been trying to solve, which is: show two months, but have some kind of visual separation (i.e. empty row) between them.
I have my custom view set-up, but have no idea where to even begin on inserting a row between months. (My initial thoughts are: it's probably easier to insert a 'row' into the calendar after it renders, as opposed to getting too deep).
I was thinking about looping through the calendar's HTML on the fc-day-top CSS class and use Moment.js to match the date and then break the row by inserting html into the DOM; but I'm not sure if that's the right approach. (please see the code below and fiddle)
I am able to select the last day of the respective month, but am now trying to figure out the best way to insert HTML into the table with correct offsets before and after the split.
Any help would be much appreciated!
var calendarEl = document.getElementById('my-calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: [ 'interaction', 'dayGrid','timeGrid', 'list' ],
header: {
left: 'prev,next today',
center: 'title',
right: 'listDay,dayGridMonth,monthView2'
},
views: {
monthView2: {
type: 'dayGrid',
duration: {
months: 2
},
buttonText: '2-Month View',
showNonCurrentDates: false,
},
dayGridMonth: {
buttonText: 'Month View',
showNonCurrentDates: false,
},
listDay: { buttonText: 'Day List' },
},
defaultView: 'monthView2',
// With the code below: my initial though is: find the last day of the month, and insert <td>s and a row to split it
datesRender: function( info ){
$('.fc-row.fc-week').each(function() {
var thisWeek = $(this);
var $d_i = 0;
var htmlCellStringBefore = htmlCellStringAfter = '';
$(thisWeek).find('.fc-day-top').each(function() {
$d_i++;
var thisDay = $(this).data('date');
var thisDateYear = moment(thisDay).year();
var thisDateMonth = moment(thisDay).month();
var lastDay = new Date(thisDateYear, thisDateMonth + 1, 0);
var lastDayMoment = moment(lastDay).format('YYYY-MM-DD');
// Match the last day, if matches, cut the table and insert HTML
if(thisDay == lastDayMoment){
var cellIteratorBefore = 7 - $d_i;
var cellIteratorAfter = 7 - cellIteratorBefore;
// Looping to create number of offset cells before break for insertion
for (i = 0; i < cellIteratorBefore; i++) {
htmlCellStringBefore += '<td class="cellBefore"></td>';
}
// Looping to create number of offset cells after break for insertion
for (i = 0; i < cellIteratorAfter; i++) {
htmlCellStringAfter+= '<td class="cellAfter"></td>';
}
var returnHtmlHead = htmlCellStringBefore + '</tr></thead>'; // inserting empty cells after date to break into head
var returnHtmlBody = htmlCellStringBefore + '</tr></tbody></table>'; // inserting empty cells after date to break into table body
var thisTableFcBG = $(thisWeek).find('.fc-bg tbody td');
var thisTableFcSkeleton = $(thisWeek).find('.fc-content-skeleton tbody td');
var thisTableFcBGNthTableCell = $(thisTableFcBG)[cellIteratorBefore];
var thisTableFcSkeletonNthTableCell = $(thisTableFcSkeleton)[cellIteratorBefore];
var MonthName = moment(lastDayMoment).add(1, 'days').format("MMMM");
$('<div class="break-month-title">'+ MonthName+ '</div>').insertAfter(thisWeek);
// This part is messy and i'm trying figure out the best way to split up the tables
$(returnHtmlHead).insertAfter(thisDay);
$(returnHtmlBody + '<div class="fc-row fc-week fc-widget-content"><div class="break-month">BREAK MONTH</div><div class="fc-bg"><table><thead><tr>'+ htmlCellStringAfter).insertAfter(thisTableFcBGNthTableCell);
$(returnHtmlBody + '<div class="fc-content-skeleton"><table><thead><tr>' + htmlCellStringAfter).insertAfter(thisTableFcSkeletonNthTableCell);
}
});
});
}
});
calendar.render();
.break-month {
background:#f10000;
}
.break-month-title {
text-align:center;
padding:3rem;
font-size:2rem;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/core/main.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://momentjs.com/downloads/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/core/main.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/interaction/main.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/daygrid/main.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/timegrid/main.min.js"></script>
<div id="my-calendar"></div>
I also have a fiddle: https://jsfiddle.net/zjr73m41/
I am trying to add no of months to a given date using js. fd_start_date has the start date, but moment.js returns "Invalid Date". I am using date picker to select date in format YYYY-MM-DD.
$('#fd_start_date').click(function () {
var start_date=$("#fd_start_date").val();
var no_of_months=$("#fd_duration").val();
var currentDate = moment(start_date);
var future_date = moment(currentDate).add(no_of_months, 'months');
console.log(future_date);
});
Works for me if I change to on input and have a value in the month field
$('#fd_start_date, #fd_duration').on("input",function() {
var start_date = $("#fd_start_date").val();
if (start_date) {
var no_of_months = $("#fd_duration").val();
var currentDate = moment(start_date);
var future_date = moment(currentDate).add(no_of_months, 'months');
console.log(future_date);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<input type="date" id="fd_start_date" /><input type="number" id="fd_duration" value="1" />
You can achieve this in the following way:
// Getting the current moment
const currentTime = moment()
// Adding a month to it
const futureMonth = currentTime.add(1, 'M');
console.log(futureMonth)
<script src="https://rawgit.com/moment/moment/2.2.1/min/moment.min.js"></script>
I am using this in my project and this logic is working fine for me.
$scope.o.DateOfBirth = "31/03/2021";
var currentDate =moment($scope.o.DateOfBirth, 'DD/MM/YYYY').format('YYYY-MM-DD');
var futureMonth = moment(currentDate ).add(24, 'month').format("YYYY-MM-DD");
console.log(currentDate.format('DD-MM-YYYY'));
console.log(futureMonth.format('DD-MM-YYYY'));
output : "2023-03-31"
I'm using JQuery datatables to sort some table with data.
I'm using custom items to sort, in my case I have a select element which sorts one of the columns. And this works.
I also have 2 inputs that serve as datepickers.
These pickers have data formatted as same as on the table, so filtering works well, but my question is:
Is possible to filter column based on the range of pickers? So for example:
from 1 sep 2017 to 10 sep 2017?
I'm was looking for some custom function in datatables docs but I found nothing so it's why I'm asking StackOverflow community.
I think I need to check when second date one was selected and then get data of first datepicker and filter column based on this. But to make things easier, when the first picker is selected I will just show the second picker, so the user may know that selecting the first picker will trigger need of selecting the second one also....
$(document).ready(function() {
var table = $('#scroll-wrc-changes-table table').DataTable({
"paging": false,
});
var picker1 = $('#datetimepicker1').datetimepicker({
format: 'DD MMM YYYY',
defaultDate: new Date(),
});
var picker2 = $('#datetimepicker2').datetimepicker({
format: 'DD MMM YYYY',
defaultDate: new Date(),
});
picker1.on('dp.change',function() {
table.columns([3] ).search( this.value ).draw();
});
picker2.on('dp.change',function() {
table.columns([3] ).search( this.value ).draw();
});
// This is just select element
$('#table-select').change(function() {
table.columns([2] ).search( this.value ).draw();
})
});
Maybe this link can help you.
Range Filtering
The idea is to make function for custom filtering.
$.fn.dataTable.ext.search.push(
function( settings, data, dataIndex ) {
var date1 = new Date( $('#datetimepicker1').val() );
var date2 = new Date( $('#datetimepicker2').val() );
var dateData = new Date( data[3] ); // use data from the date column
if ( dateData >= date1 && dateData <= date2 )
{
return true;
}
return false;
});
Hope this help..
Asuming you are using ajax datatable . If not draw idea from this example
Add a row where you can set range for filter as:
<div class="col-md-3"> <label>From:</label> <input readonly="readonly" type="text" id="mindate" class="srchdp"> <i class="fa fa-times-circle-o" id="clear-mindate"></i></div>
<div class="col-md-3"> <label>To:</label> <input readonly="readonly" type="text" id="maxdate" class="srchdp"> <i class="fa fa-times-circle-o" id="clear-maxdate" ></i></div>
<div class="col-md-2"><button class="btn btn-primary" id="filter-record">Filter</button></div>
//initialize datepicker as
$("input:text.srchdp").datetimepicker({
changeMonth: true,
changeYear: true,
yearRange: "-100:+0",
dateFormat: 'mm/dd/yy',
controlType: 'select',
timeFormat: 'hh:mm:ss TT',
})
// now keep a event on filter button click
$(document).on("click", "#filter-record", function () {
assetListVM.search("").draw();
});
// now on ajax request
public ActionResult Get([ModelBinder(typeof(DataTablesBinder))] IDataTablesRequest requestModel, string mindate,string maxdate, string searchbase)
{
DataBaseEntities db = new DataBaseEntities();
IQueryable<Wishlist> query = db.Wishlists;
var totalCount = query.Count();
#region Filtering
// Apply filters for searching
var value = requestModel.Search.Value.Trim();
if (!string.IsNullOrEmpty(searchbase))
{
if (!string.IsNullOrEmpty(mindate) && !string.IsNullOrEmpty(maxdate))
{
DateTime datevaluemin;
DateTime datevaluemax;
var mindateval = DateTime.TryParse(mindate, out datevaluemin);
var maxdateval = DateTime.TryParse(mindate, out datevaluemax);
if (mindateval && maxdateval)
{
var minvalue = Convert.ToDateTime(mindate);
var maxvalue = Convert.ToDateTime(maxdate);
if (searchbase == "CreatedDate")
{
query = query.Where(p =>
p.CreatedDate >= minvalue
&& p.CreatedDate <= maxvalue);
}
}
}
else if (!string.IsNullOrEmpty(mindate))
{
DateTime datevalue;
var mindateval = DateTime.TryParse(mindate, out datevalue);
if (mindateval)
{
var minvalue = Convert.ToDateTime(mindate);
if (searchbase == "CreatedDate")
{
query = query.Where(p =>
p.CreatedDate >= minvalue
);
}
}
}
}
if (requestModel.Search.Value != string.Empty)
{
query = query.Where(p => p.Id.ToString().Equals(value) ||
p.ProductId.ToString().Equals(value) ||
p.MemberId.ToString().Contains(value)
);
}
var filteredCount = query.Count();
#endregion Filtering
#region Sorting
// Sorting
var sortedColumns = requestModel.Columns.GetSortedColumns();
var orderByString = String.Empty;
foreach (var column in sortedColumns)
{
orderByString += orderByString != String.Empty ? "," : "";
orderByString += (column.Data) + (column.SortDirection == Column.OrderDirection.Ascendant ? " asc" : " desc");
}
query = query.OrderBy(orderByString == string.Empty ? " asc" : orderByString);
#endregion Sorting
// Paging
query = query.Skip(requestModel.Start).Take(requestModel.Length);
var data = query.Select(asset => new
{
Id = asset.Id,
ProductId = asset.ProductId,
ProductName = asset.Product.ProductName,
MemberId=asset.MemberId,
CreatedDate = asset.CreatedDate.ToString(),
}).ToList();
return Json(new DataTablesResponse(requestModel.Draw, data, filteredCount, totalCount), JsonRequestBehavior.AllowGet);
}
}
}
this code is not complete hence it doesn't work alone.
I want to get a range of items between dates from two JQuery calendars and then update the view when I press a submit button so that I only see the items between the selected dates. I'm not sure I'm going about things the best way.
My plan was to:
Get the user to select the dates in the calendars.
Use Javascript to return the dates as variables.
Send the variables to a controller which would then return a new view.
My code is below and my question is really in two parts.
Is there a better way to do this?
If this is ok, how can I get the javascript variables into the ActionLink to pass back to the controller?
Thanks in advance!
Controller:
// GET: Home
public ActionResult IndexDateRange(string sortOrder, DateTime startDateFromJS, DateTime endDateFromJS)
{
var sortedByDates = from pay in db.DailyPayments
select pay;
sortedByDates = sortedByDates.OrderByDescending(pay => pay.Date);
var first = sortedByDates.Select(pay => pay.Date).First();
var lastDate = sortedByDates.Select(pay => pay.Date).Last();
if (startDateFromJS > first.Date || (endDateFromJS < lastDate))
{
var dateRange = sortedByDates.Where(pay => pay.Date >= startDateFromJS && pay.Date <= endDateFromJS);
return View(dateRange.ToList());
}
return View(sortedByDates.ToList());
}
Javascript in the Index:
#Html.ActionLink("Get Dates", "IndexDateRange", routeValues: new { startDateFromJS = startDate, endDateFromJS = endDate })
<script>
$(function () {
var startDate = getStartDate();
var endDate = getEndDate();
function getStartDate() {
$('#startDate').datepicker();
$('#calendarSubmitButton').click(function () {
//var startDate = $('#startDate').datepicker('getDate');
var startDate = $('#startDate').datepicker('getDate');
console.log(startDate);
return startDate;
})
};
function getEndDate() {
$('#endDate').datepicker();
$('#calendarSubmitButton').click(function () {
var endDate = $('#endDate').datepicker('getDate');
console.log(endDate);
return endDate;
})
};
Temporary Test JS to try and wire up the href. When I click on it, it just adds the pound symbol to the home/index Url and in the browser developer tools it says illegal character.
Get Dates
<script type="text/javascript">
$('#calendarSubmitButton').click(function() {
var tempStartDate = #DateTime.Now.AddMonths(-1).ToString("yyyyMMdd");
var tempEndDate = #DateTime.Now.ToString("yyyyMMdd");
location.href='#Url.Action("IndexDateRange")+'?startDateFromJS='+$('tempStartDate')+'&endDateFromJS='+$('tempEndDate')';
});
</script>
Screen Grab:
Screenshot of the setup
Try this
Get Dates
<script type="text/javascript">
$('#calendarSubmitButton').click(function() {
var tempStartDate = '#DateTime.Now.AddMonths(-1).ToString("yyyyMMdd")';
var tempEndDate = '#DateTime.Now.ToString("yyyyMMdd")';
location.href='#Url.Action("IndexDateRange")?startDateFromJS='+tempStartDate +'&endDateFromJS='+tempEndDate;
});
</script>
Thanks to the help of #StephenMuecke and #Tanmay, I was finally able to get this to work. I'm posting the functioning code here.
Controller
// GET: Home
public ActionResult Index(string sortOrder, string startDate, string endDateFromJS)
{
var sortedByDates = from pay in db.DailyPayments
select pay;
sortedByDates = sortedByDates.OrderByDescending(pay => pay.Date);
if (startDate != null && endDateFromJS != null)
{
DateTime convertedStartDateFromJS = DateTime.ParseExact(startDate, "yyyyMMdd", new CultureInfo("en-US"));
DateTime convertedEndDateFromJS = DateTime.ParseExact(endDateFromJS, "yyyyMMdd", new CultureInfo("en-US"));
var dateRange = sortedByDates.Where(pay => pay.Date >= convertedStartDateFromJS && pay.Date <= convertedEndDateFromJS);
return View(dateRange.ToList());
}
return View(sortedByDates.ToList());
}
Javascript and HTML in the index.cshtml
<div class="form-group">
#Html.Label("Total payment:", new { id = "totalTextbox" }) <br />
#Html.TextBox("Total", Math.Floor(totalPayment) + " yen" , new { #class = "alert alert-danger", #readonly = "readonly" })
</div>
<div class="form-group">
#Html.Label("Starting Date:")
#Html.TextBox("Starting Date:", "", new { #class = "date-picker", id = "startDate" })
#Html.Label("Ending Date:")
#Html.TextBox("Ending Date:", "", new { #class = "date-picker", id = "endDate" })
#*<input type="submit" href="#" id="calendarSubmitButton" class="btn btn-primary" />*#
Get Dates
<script type="text/javascript">
$(document).ready(function () {
$('#calendarSubmitButton').click(function () {
//TODO: Figure this out.
var tempStartDate = $("#startDate").val($.datepicker.formatDate('yymmdd', new Date($('#startDate').datepicker('getDate'))));
var tempEndDate = $("#endDate").val($.datepicker.formatDate('yymmdd', new Date($('#startDate').datepicker('getDate'))));
location.href = '#Url.Action("Index")?startDate=' + tempStartDate.val() + '&endDateFromJS=' + tempEndDate.val();
})
});
</script>
</div>
I would like to make redirect when a date is changed and transmit selected date parameter (via window.location.href). I'm using Bootstrap Date Paginator, which contains Bootstrap datepicker, but I don't know how to change these lines of code to work properly:
this.$calendar
.datepicker({
options...
})
.datepicker('update', this.options.selectedDate.toDate())
.on('changeDate', $.proxy(this._calendarSelect, this));
I know I would use changeDate event but there aren't any examples of using this event. Can you help me, please?
Would this do?
You can use .on('change', ..) like this,
this.$calendar
.datepicker({
options...
}).on('change', function() {
var changedDate = this.$calendar.val();
//alert("value of date is "+ x);
var theUrl = 'your URL';
window.location.href = theUrl+"date="changedDate
});
Else use, on('change.dp', ..) event like this,
this.$calendar
.datepicker({
options...
}).on('change.dp', function() {
var changedDate = this.$calendar.val();
//alert("value of date is "+ x);
var theUrl = 'your URL';
window.location.href = theUrl+"date="changedDate
});
Alternatively have a look at this too.
May be it's too late, but I have same problem and come up with this solution,
while setting options for Bootstrap Date Paginator keep track of onSelectedDateChanged function and assign the date value to a variable and send that variable to location.href.
<script>
var currDate = new Date();
var options = {
selectedDateFormat: 'DD/MM/YYYY',
selectedDate: moment(currDate).format('DD/MM/YYYY'),
onSelectedDateChanged: function (event, date) {
var dateSelected = moment(date).format('DD/MM/YYYY');
location.href = '/ServletName?timestamp='+currDate .getTime() + "&date=" + dateSelected ;
},
};
$('#paginator').datepaginator(options);
</script>
<body>
<div id="paginator"></div>
</body>