How to Increase Date after the time in Timepicker passes midnight? - javascript

I have a startDate model which I have bound to a bootstrap date picker and timepicker. When I increase the time in the Time picker and it passes midnight, I need to have the model increase its date as well. Following is my existing code.
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('DatepickerDemoCtrl', function($scope) {
$scope.hstep = 1;
$scope.mstep = 15;
$scope.ismeridian = true;
$scope.toggleMode = function() {
$scope.ismeridian = !$scope.ismeridian;
};
$scope.today = function() {
$scope.startDate = new Date();
};
$scope.startDateState = {
opened: false
}; /* Model to keep track if Popup is open */
$scope.today(); /* Sets Date as Today Initially */
$scope.showWeeks = false; /* Hides Week Numbers */
$scope.minDate = new Date(); /* Disables past dates */
$scope.format = 'dd MMM, yyyy'; /* Date Format Setting */
$scope.dateOptions = {
startingDay: 1,
showWeeks: false,
}; /* to be passed in the date-options directive */
$scope.open = function() {
$scope.startDateState.opened = true;
}; /* Button Click Event to open Popup */
});
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.14.3.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="DatepickerDemoCtrl">
<pre>Start date is: <em>{{startDate| date:"MM/dd/yyyy 'at' h:mma"}}</em></pre>
<div class="row">
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="startDate" is-open="startDateState.opened" on-open-focus="false" min-date="minDate" show-button-bar="false" datepicker-options="dateOptions" ng-required="true" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open()"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
<uib-timepicker ng-model="startDate" hour-step="hstep" minute-step="mstep" show-meridian="ismeridian"></uib-timepicker>
</div>
</div>
</div>
</body>
</html>
How to approach this problem?

Akash,
The way I approached the problem was to use the ng-change directive on the date input field.
HTML
<input ... ng-change="startDateChanged({{startDateTime}})"></input>
You will notice that the parameter being passed to the controllers scope function is a literal expression. The reason for this is so that we can compare what the original value of the ng-model date object was before it was modified by the up or down arrows from the time picker.
Controller
var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('MainCtrl', function($scope) {
var twelveAm = 0;
var oneAm = 1;
var elevenPm = 23;
$scope.hStep = 1;
$scope.mStep = 15;
$scope.startDateTime = new Date();
$scope.today = new Date();
$scope.datePickerState = {
startDateOpened: false
};
$scope.datePickerOptions = {
"show-weeks": false
};
$scope.open = () => {
$scope.datePickerState.startDateOpened = true;
};
$scope.startDateChanged = (originalModel) => {
var nd = _.clone($scope.startDateTime);
var od = new Date(originalModel);
if (nd.getHours() === twelveAm) {
if (od.getHours() === elevenPm) {
nd.setDate(nd.getDate() + 1);
$scope.startDateTime = nd;
} else if (od.getHours() === oneAm) {
nd.setDate(nd.getDate() - 1);
$scope.startDateTime = nd;
}
}
};
});
Inside the method $scope.startDateChanged(), I first create two new date objects, one holding the value of the original datetime (the expression that was passed in) and another with the new datetime. Then I check to see if the new datetime (nd) has a value of 12 AM. If it does, I then check to see if the original datetime (od) has a value of 11 PM or 1 AM and act accordingly (if its 11 PM, it means the button we pushed was to increase the time and therefore the day, otherwise, we are lowering the time and henceforth the day)
I've included a Plunker to illustrate the example.
https://plnkr.co/edit/dDMfpXmy3JBEjXzOca9v

Related

Update View from Click in Angular

I am trying to update a date dynamically from a user clicking a forward or backward button, but can't seem to figure out how to make the data change from the view.
The variable date changes but not from the browser.
< July 31, 2017 >
Example pic
EDIT: I had originally put my methods inside the constructor (I don't have it that way in my code, but rather me mistyping it in the question here)
App Component
export class AppComponent {
date: Date;
constructor () {
this.date = new Date();
}
dateForward() {
this.date.setDate(this.date.getDate() + 1);
}
dateBack() {
this.date.setDate(this.date.getDate() - 1);
}
}
HTML Template
<i (click)="dateBack()" class="fa fa-chevron-left" ></i>
<a>{{date | date:'MMM d, y'}}</a>
<i (click)="dateForward()" class="fa fa-chevron-right"></i>
Beside not puting your methods inside your constructor you should pay attention to change detection and immutability
this.date.setDate(this.date.getDate() + 1) will not trigger change detection, to enforce that you need this.date = new Date(this.date.setDate(this.date.getDate() + 1));, the change detector will notice the change only if you change to a different object entirely and not when you set an object properties, same thing with arrays
constructor() {
this.date = new Date();
}
dateForward() {
this.date = new Date(this.date.setDate(this.date.getDate() + 1));
}
dateBack() {
this.date = new Date(this.date.setDate(this.date.getDate() - 1));
}
You should not put your functions in your constructor. Instead, you should create methods in your class, this will allow you to call them in your HTML template.
public date: Date;
constructor() {
this.date = new Date();
}
public dateForward = () => this.date.setDate(this.date.getDate() + 1);
public dateBack = () => this.date.setDate(this.date.getDate() - 1);
methods should not be inside constructor
date :Date;
constructor() {
this.date = new Date();
}
dateForward() {
this.date = new Date(this.date.setDate(this.date.getDate() + 1));
}
dateBack() {
this.date = new Date(this.date.setDate(this.date.getDate() -1 ));
}
Working Plunker link
in angular inside controller you can define a $scope variable lets say you call that variable date.
e.g. $scope.date = new Date().getDate();
Then inside your html you can access it
<div> {{date}} </div>
And whenever you click your call to action buttons you can change the value of this $scope variable and as soon as it will change the value of HTML will be updated automatically.
You can run the following code to see the example.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<h1>{{date | date:'MMM d, y'}}</h1>
Back
Forward
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.date = new Date();
$scope.dateBack = function(){
$scope.date.setDate($scope.date.getDate() - 1);
};
$scope.dateForward = function(){
$scope.date.setDate($scope.date.getDate() + 1);
};
});
</script>
</body>
</html>

In MVC, how do I return items in and Entity database using a range of dates from Javascript Calendar

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")+'?startDateFrom‌​JS='+$('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")?startDateFrom‌​JS='+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>

Input a number and showed it in 'hh:mm:ss' /time format in AngularJS

Im making function in my app that when I entered a specific number, It will display the in hh:mm:ss format and start counting down. The input number will be treated as minutes for example when I input 2, the display would be 00:02:00 then it will start counting down.
<body ng-app="mehmetcankerApp">
<!--counterCtrl App Controller -->
<div ng-controller="counterCtrl">
<!--Angular Binding -->
<input type="number" ng-model="counter"/>
<p ng-model="format" ng-bind="counter" id="numOfDozens"></p>
<button ng-click="stop()">Stop</button>
<button ng-click="countdown()">Start</button>
</div>
The whole code is in this plnker link: http://plnkr.co/edit/Mzv6W9smmRkaDPU4cgVa?p=preview
You need to use a custom filter and an interval:
var app = angular.module('app', []);
app.controller('counterCtrl', ['$scope', '$interval',
function($scope, $interval) {
$scope.minutes = 0;
$scope.seconds = $scope.minutes * 60;
$scope.$watch('minutes', function() {
$scope.seconds = $scope.minutes * 60;
});
$scope.countdown = function() {
if ($scope.seconds <= 0) return;
$scope.countdownInterval = $interval(function() {
if ($scope.seconds <= 0) {
$interval.cancel(countdownInterval);
}
$scope.seconds--;
}, 1000);
};
$scope.stop = function() {
$interval.cancel($scope.countdownInterval);
};
}
]);
app.filter('secondsToDate', [
function() {
return function(seconds) {
return new Date(1970, 0, 1).setSeconds(seconds);
};
}
])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="counterCtrl">
<!--Angular Binding -->
<input type="number" ng-model="minutes" />
<p id="numOfDozens">{{seconds | secondsToDate | date:'HH:mm:ss'}}</p>
<button ng-click="stop()">Stop</button>
<button ng-click="countdown()">Start</button>
</div>
</div>
Working Demo
Here you can see that, I have created a function to get a sample date with exact time of the inputted text (counter).
{{getMyTime() | date: 'HH:mm:ss'}}
getMyTime() will return a sample date with correct time and formatted it with date filter.
$scope.getMyTime = function(){
var myTime = new Date(01,01,01);
myTime.setMinutes($scope.counter);
return myTime;
}
Hope this will help you.
Please feel free to ask any doubt on this !!!

knockout mvvm binding with metro.js datepicker

I was trying to hack my way around with the metro.js datepicker and knockout. So far my datepicker binding code looks like:
ko.bindingHandlers.datepicker = {
init: function(el, va, ba, model, ctx) {
var prop = va();
$(el).datepicker({
onSelect: function(txt, date) {
prop(date);
}
});
},
update: function(el, va, ba, model, ctx) {
var prop = va();
var date = ko.unwrap(prop);
if(date) {
applyDate(date);
}
function applyDate(dt) {
var j = $(el);
var dp = j.data('datepicker');
var inp = j.find('input');
var fmt = dp.options.format;
var sDate = format(fmt, dt);
// dp._calendar.calendar.dayClick(sDate, dt);
// inp.value = sDate;
dp._calendar.calendar('setDate', sDate);
j.find('input').val(dp._calendar.calendar('getDate')).trigger('change', sDate);
}
function format(fmt, dt) {
fmt = fmt.replace('yyyy', dt.getFullYear());
fmt = fmt.replace('mm', pad(dt.getMonth() + 1));
fmt = fmt.replace('dd', pad(dt.getDate()));
return fmt;
}
function pad(n) {
return parseInt(n) < 10 ? '0' + n: '' + n;
};
}
}
Issue is that when I issue a model update on the date property its bound to the datepicker doesn't update. I mean, it does it the very first time, but post that, it fails to update the textbox; calendar shows okay however. Ultimately I need to change the logic in the applyDate function...
JSBin: http://jsbin.com/rupaqolexa/1/edit?html,js,output
Update: Another issue just cropped up...it doesn't work in IE 10+. The date appears as NaN in the UI...
Update: Steps for reproduction
type date 2nd text box: 2013/05/13 & click on the Change button. Observe date is updated in the datepicker textbox. This works as expected. (Except in IE).
type another date in the textbox & click the change button. Observe the date is not updated in the datepicker textbox. Expected here that the datepicker textbox updates with latest value.
In the update part of your custom binding you need to make all the changes to the bound elements, which include the calendar widget, and the related input element.
I've modified the code to do so, so that it now works.
function ViewModel(date) {
var model = this;
model.date = ko.observable(date);
model.set = function() {
var val = $('#somedate').val();
var dt = new Date(val);
model.date(dt);
};
}
ko.bindingHandlers.datepicker = {
init: function(el, va, ba, model, ctx) {
var prop = va();
$(el).datepicker({
onSelect: function(txt, date) {
prop(date);
}
});
},
update: function(el, va, ba, model, ctx) {
var newDate = ko.unwrap(va());
if(newDate) {
var $el = $(el);
var datePicker = $el.data('datepicker');
var $input = $el.find('input');
var formattedDate = format(datePicker.options.format, newDate);
datePicker._calendar.calendar('setDate', formattedDate);
$input.val(formattedDate);
//$input.val(dp._calendar.calendar('getDate'))
// .trigger('change', sDate);
}
function format(fmt, dt) {
fmt = fmt.replace('yyyy', dt.getFullYear());
fmt = fmt.replace('mm', pad(dt.getMonth() + 1));
fmt = fmt.replace('dd', pad(dt.getDate()));
return fmt;
}
function pad(n) {
return parseInt(n) < 10 ? '0' + n: '' + n;
}
}
};
var m = new ViewModel();
$(function(){
ko.applyBindings(m);
});
<link href="//metroui.org.ua/css/metro.css" rel="stylesheet">
<link href="//metroui.org.ua/css/metro-icons.css" rel="stylesheet">
<link href="//metroui.org.ua/css/metro-responsive.css" rel="stylesheet">
<link href="http://metroui.org.ua/css/metro-schemes.css" rel="stylesheet">
<script src="http://metroui.org.ua/js/jquery-2.1.3.min.js"></script>
<script src="http://metroui.org.ua/js/metro.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-debug.js"></script>
<div>
<div class="input-control text" data-bind="datepicker: date">
<input type="text">
<button class="button"><span class="mif-calendar"></span></button>
</div>
</div>
<div>
<label>Date</label>
<div class="input-control text">
<input type="text" id="somedate"/>
</div>
<input type="button" class="button" value="Change" data-bind="click: set"/>
</div>
<div>
<code data-bind="text: date"></code>
</div>
However there is still a little hiccup: the datepiceker's calendar setdate adss new selected date, instead of replacing selected ones. Please, see the API docs to solve this yourself.

angularJS Resetting $Scope Values On Button Click

I have a AngularJS SPA what contains a text input on a modal, on Page load the modals inputs are set to their desired initial state through a scope function which is called.
Modal
<input class="form-control" ng-model="PatientName" name="PatientName" id="PatientName" />
<button type="button" class="btn btn-default" ng-click="setvals()" data-dismiss="modal">Close</button>
App.js
var app = angular.module("TrollyPatientApp", ['TrollyPatientFilters']);
app.controller("NewPartientModalController", function ($scope, $filter) {
console.log("controller Loaded...")
$scope.setvals = function () {
console.log($scope);
console.log("Setting Intial New Patient Values.")
$scope.PatientName = "john";
$scope.setDateAsNowCB = true; //True = Readonly, false = enabled.
$scope.ArrivalDateInEd = $filter('date')(new Date(), 'dd/MM/yyyy');//Injecting the date (through the filter) into the ArrivalDateInED field.
console.log($scope);
}
$scope.setvals();
});
When the close button is clicked on the modal i want it to reset all the values back to default.
At present it does this by calling setvals(). I can see it being called from the debug console however it doesn't seem to effect the input value....
On load you should create a object patient that would have all the information about the patient, store it inside some variable on init. & on reset rebind that copy to the actual patient model.
Controller
app.controller("NewPartientModalController", function ($scope, $filter) {
console.log("controller Loaded...")
$scope.patient = {};
$scope.setvals = function () {
console.log($scope);
console.log("Setting Intial New Patient Values.")
$scope.patient.PatientName = "john";
$scope.patient.setDateAsNowCB = true; //True = Readonly, false = enabled.
$scope.patient.ArrivalDateInEd = $filter('date')(new Date(), 'dd/MM/yyyy');//Injecting the date (through the filter) into the ArrivalDateInED field.
//save copy of initial object in some variable
$scope.copyOfInitialPatient = angular.copy($scope.patient);
}
$scope.reset = function(){
//assign initial copy again to patient object.
$scope.patient = angular.copy($scope.copyOfInitialPatient);
}
$scope.setvals();
});
You need to define $scope.PatientName = "john"; outside of $scope.setvals for first, then changing value in setvals() will work.
var app = angular.module("TrollyPatientApp", []);
app.controller("NewPartientModalController", function ($scope, $filter) {
console.log("controller Loaded...")
$scope.PatientName = "john";
$scope.setvals = function () {
console.log($scope);
console.log("Setting Intial New Patient Values.")
$scope.PatientName = "john";
$scope.setDateAsNowCB = true; //True = Readonly, false = enabled.
$scope.ArrivalDateInEd = $filter('date')(new Date(), 'dd/MM/yyyy');//Injecting the date (through the filter) into the ArrivalDateInED field.
console.log($scope);
}
$scope.setvals();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="TrollyPatientApp" ng-controller="NewPartientModalController">
<input class="form-control" ng-model="PatientName" name="PatientName" id="PatientName" />
<button type="button" class="btn btn-default" ng-click="setvals()" data-dismiss="modal">Close</button>
</body>

Categories

Resources