angular bootstrap datepicker get visible dates (day mode) - javascript

I need to get visible dates from the Datepicker if mode is day.
Example:
In this case I need to get these 42 days. Also if user change month, I should refresh the Datepicker controller view and get new 42 days.

So i managed to fix this.
We need to extend uibDatepickerDirective
angular.module('ui.bootstrap.datepicker')
.config(function ($provide) {
$provide.decorator('uibDatepickerDirective', function ($delegate, $timeout) {
var directive = $delegate[0];
var link = directive.link;
angular.extend(directive.scope, {
visibleDates: '=?'
});
directive.compile = function () {
return function (scope, element, attrs, ctrls) {
link.apply(this, arguments);
var datepickerCtrl = ctrls[0];
datepickerCtrl.getVisibleDates = function () {
var year = this.activeDate.getFullYear(),
month = this.activeDate.getMonth(),
firstDayOfMonth = new Date(this.activeDate);
firstDayOfMonth.setFullYear(year, month, 1);
var difference = this.startingDay - firstDayOfMonth.getDay(),
numDisplayedFromPreviousMonth = difference > 0 ?
7 - difference : -difference,
firstDate = new Date(firstDayOfMonth);
if (numDisplayedFromPreviousMonth > 0) {
firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
}
return this.getDates(firstDate, 42);;
}
var firstTime = true;
$timeout(function () {
scope.$watch("activeDt", function () {
var newValues = datepickerCtrl.getVisibleDates();
if (firstTime) {
scope.visibleDates = newValues;
firstTime = false;
return;
}
if (newValues[0].getYear() !== scope.visibleDates[0].getYear() ||
newValues[0].getMonth() !== scope.visibleDates[0].getMonth() ||
newValues[0].getDate() !== scope.visibleDates[0].getDate()) {
scope.visibleDates = newValues;
}
});
});
}
};
return $delegate;
});
});
And in directive itself we need to pass atribute visible-dates and point to the variable where we want to save these 42 days.
<span uib-datepicker visible-dates="visibleDates" datepicker- ng-model="datePicked"></span>
This way we will update visibleDates (42 of them) if we change month in datepicker, but if we change activeDate (scope.activeDt) on the same month (same visible dates), it will stay unchanged.

Related

How to use a function independently on each line of table row in AngularJs

I have created a timer function that take a future date as String and take difference from current date for HH:MM:SS and start a decrease timer. When timers becomes 00:00:00, it should blink the row of table.
I have created function and timer and row also started blinking. But timer is showing same value to all rows and all rows started blinking. I want this independently for each row i.e. each row should have its independent timer display not same value in each.
Below is function inside Controller-
$scope.timeInitializer = function (timeFromApi) {
$scope.blinkAlarmOn = false;
$scope.currentTimeUTCMiliSec = new Date(new Date().toUTCString()).getTime();
$scope.targetDeployDate = timeFromApi.split('.')[0]+"Z";
$scope.deployTimeUTCMiliSec = new Date(new Date(Date.parse($scope.targetDeployDate)).toUTCString()).getTime();
$scope.differenceDateUTC = new Date($scope.deployTimeUTCMiliSec - $scope.currentTimeUTCMiliSec).toUTCString();
$scope.totalSecondLeft = Math.floor(($scope.deployTimeUTCMiliSec - $scope.currentTimeUTCMiliSec)/1000);
$scope.c = $scope.totalSecondLeft;
$scope.hrs = new Date($scope.differenceDateUTC).getUTCHours();
$scope.mins=new Date($scope.differenceDateUTC).getUTCMinutes();
$scope.secs=new Date($scope.differenceDateUTC).getUTCSeconds();
$scope.temp = $interval(function () {
if ($scope.c != 0 && $scope.secs > 0) {
$scope.c--;
$scope.secs--;
if ($scope.secs == 0 && $scope.mins > 0) {
$scope.mins--;
$scope.secs=59;
if ($scope.mins==0 && $scope.hrs > 0) {
$scope.hrs--;
$scope.mins = 59;
}
}
}
if( ($scope.hrs == 0) && ($scope.mins == 0) && ($scope.secs == 0)) {
$interval.cancel($scope.temp);
$scope.blinkAlarmOn=true;
}
},1000);
};
Calling function inside UI
<td>
<div ng-show="tckt.state=='DELAY_DEPLOYMENT'"
ng-if="tckt.state=='DELAY_DEPLOYMENT'" ng-
init="timeInitializer(tckt.deploymentDatetime)">{{hrs+":"+mins+":"+secs}}
</div>
</td>
For independent scope or functioning, we can use AngularJs custom Directive.
mainApp.directive('countdown', function() {
return {
restrict: 'E',
template: '<div>{{countdownVal}}</div>',
scope: {
initVal: '='
},
controller: function($scope, $interval) {
if($scope.initVal){
$scope.blinkAlarmOn=false;
$scope.currentTimeUTCMiliSec=new Date(new Date().toUTCString()).getTime();
$scope.targetDeployDate=$scope.initVal.split('.')[0]+"Z";
$scope.deployTimeUTCMiliSec=new Date(new Date(Date.parse($scope.targetDeployDate)).toUTCString()).getTime();
if($scope.deployTimeUTCMiliSec > $scope.currentTimeUTCMiliSec){
$scope.differenceDateUTC=new Date($scope.deployTimeUTCMiliSec-$scope.currentTimeUTCMiliSec).toUTCString();
$scope.totalSecondLeft=Math.floor(($scope.deployTimeUTCMiliSec-$scope.currentTimeUTCMiliSec)/1000);
$scope.c=$scope.totalSecondLeft;
$scope.hrs=new Date($scope.differenceDateUTC).getUTCHours();
$scope.mins=new Date($scope.differenceDateUTC).getUTCMinutes();
$scope.secs=new Date($scope.differenceDateUTC).getUTCSeconds();
$scope.temp=$interval(function () {
if($scope.c!=0 && $scope.secs>0){
$scope.c--;
$scope.secs--;
if($scope.secs==0 && $scope.mins>0){
$scope.mins--;
$scope.secs=59;
if($scope.mins==0 && $scope.hrs>0){
$scope.hrs--;
$scope.mins = 59;
}
}
}
if(($scope.hrs==0)&&($scope.mins==0)&&($scope.secs==0)){
$interval.cancel($scope.temp);
$scope.blinkAlarmOn=true;
}
$scope.countdownVal = $scope.hrs+":"+$scope.mins+":"+$scope.secs;
},1000);
if(($scope.hrs==0)&&($scope.mins==0)&&($scope.secs==0)){
$scope.countdownVal ="Timeout";
}else{
$scope.countdownVal = $scope.hrs+":"+$scope.mins+":"+$scope.secs;
}
}else{
$scope.countdownVal ="Timeout";
}
}else{
$scope.countdownVal ="No delay time Available.";
}
}
}
});
<countdown init-val=tckt.fuelendDateTime></countdown>

Angularjs input string to time format

I am new to angular. I am working in uib time picker, it doesn't accept the string time.
For example, I have time from json like "06:00". I need 24hrs and 12hrs format also. The problem is I am creating the directive for display time in ng-model, and I have a text input also. Suppose if I enter the value in input text, example 1111, it is needed to be formatted to 11:11
Some other examples: 183 - 18:03 , 18349 - 18:34:09 like this.
Please some one help me to solve this problem.
dateTimeMask.directive('timeMask', function($filter) {
return {
restrict: 'A',
priority: 1,
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
var timeFormat;
function formatter(value) {
var formattedValueLength = timeFormat.length;
var unformattedValueLength = timeFormat.replace(':', '').length;
var timeMask = new String(timeFormat);
if (ngModel.$isEmpty(value)) {
return value;
}
if (!value) {
ngModel.$setValidity('time', true);
return null;
} else if (angular.isDate(value) && !isNaN(value)) {
ngModel.$setValidity('time', true);
return value;
}
else if (angular.isString(value)) {
var timeRegex = /^(0?[0-9]|1[0-2]):[0-5][0-9] ?[a|p]m$/i;
if (!scope.showMeridian) {
timeRegex = /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/;
}
if (!timeRegex.test(value)) {
ngModel.$setValidity('time', false);
return undefined;
}
else {
ngModel.$setValidity('time', true);
var date = new Date();
var sp = value.split(":");
var apm = sp[1].match(/[a|p]m/i);
if (apm) {
sp[1] = sp[1].replace(/[a|p]m/i, '');
if (apm[0].toLowerCase() == 'pm') {
sp[0] = sp[0] + 12;
}
}
date.setHours(sp[0], sp[1]);
return date;
}
}
else {
ngModel.$setValidity('time', false);
return undefined;
}
}
var showTime = function(data) {
timeFormat = (!scope.showMeridian) ? "HH:mm" : "hh:mm a";
return $filter('date')(formatter(data), timeFormat);
};
scope.$watch('showMeridian', function(value) {
var myTime = ngModel.$modelValue;
if (myTime) {
element.val(showTime(myTime));
}
});
ngModel.$formatters.push(function (value) {
timeFormat = (!scope.showMeridian) ? "HH:mm" : "hh:mm a";
var date = formatter(value);
return date;
});
ngModel.$parsers.push(function (value) {
var date = showTime(value);
return date;
});
} //link function
};
});
Here is my html code which will display the time in pop up i need to update both text and popup values please some one to help me to solve this problem.

The angular datepicker totally mis-behavior as expectation

I ran into a deadly chaos on datepicker issues.
Who can solve my problem I can give 100 point as a return.
When I click the calendar on 2016-08-23 it will show me the 2016-08-22 as the date value.
Furthermore, the date value in angular model is also not correct.
I want to make the output can be consistent.
To reproduce the buggy issue, change your timezone between LA and TOKYO
DEMO site: https://test.jiyubi.com/tour_package/home
controller js
app.controller('tourPackageStartDatePickerCtrl',
function ($scope) {
$scope.initStartDate = function () {
$scope.startDate = $scope.startDate || null;
};
$scope.initStartDate();
$scope.dateOptions = {
baseDate: $scope.startDate,
minDate: $scope.startDate || moment.utc().toDate(),
};
$scope.openStartDateClick = function () {
$scope.startDatePopup.opened = true;
};
});
app.controller('tourPackageEndDatePickerCtrl',
function ($scope, $rootScope) {
$scope.clear = function () {
$scope.endDate = null;
};
$scope.endDateOptions = {
dateDisabled: disabledDays,
baseDate: new Date(),
};
$scope.openEndDateClick = function () {
$scope.endDatePopup.opened = true;
};
$scope.$watch("endDate", function (new_val, old_val) {
if (new_val && moment(new_val).isValid()) {
setTravelDateRange($scope.startDate, $scope.endDate);
}
}, true)
function setTravelDateRange(startDate, endDate) {
var start_date = moment_with_TAIPEI_TZ(startDate).format("YYYY/MM/DD");
var end_date = moment_with_TAIPEI_TZ(endDate).format("YYYY/MM/DD");
moment(startDate.toDateString()).tz("Asia/Taipei").format("YYYY/MM/DD");
$scope.q_param.startDate = start_date;
$scope.q_param.date_range = start_date + "-" + end_date;
}
});
helper.js
function moment_with_TAIPEI_TZ(time){
return moment(time).tz("Asia/Taipei");
}
function MOMENT_WITH_LOCAL(time){
return moment(time).local();
}
function discard_timezone(value) {
return moment.utc(value).format(DEFAULT_MOMENT_TIME_FORMAT);
}
function getYYYYMMDD(value) {
return moment.utc(value).format("YYYY/MM/DD");
}
function date_without_timezone(value) {
return moment.utc(value).toDate();
}
It's may be because of a timezone issue.
Could you please try to convert to date without considering the timezone?
this.convertToDateWithoutTimezone = function(date) {
if (date.toString().match(/(\d\d\d\d)-(\d\d)-(\d\d)/)) {
var year = $filter('date')(date.slice(0, 10), 'yyyy'),
month = $filter('date')(date.slice(0, 10), 'MM'),
day = $filter('date')(date.slice(0, 10), 'dd');
return new Date(year, month - 1, day);
} else {
return new Date(date);
}
};

wrapping bootstrap datepicker as a directive

I am trying to wrap the bootstrap datepicker with an angular directive
in addition to the common datepicker this datepicker contains a different dateformat for display and different date format for the ng-model.
and getting an error of :
Error: [$rootScope:inprog] $digest already in progress
my code is pasted below:
app.directive('ngDatePicker', function () {
return {//this datePicker will show the date in the wanted format and save it (ng-model) with the default format of yy-mm-dd
template: "<span><input id='displayDate' class={{class}} type='text'/><input id='hiddenDate' type='text' style='display:none'/></span>",
require: 'ngModel',
replace: true,
scope: {
ngModel: '=',
class: '#'
},
link: function (scope, element, attrs, ngModelCtrl) {
// set date pickers - this datePicker
var displayInput = element.find('#displayDate');
var hiddenInput = element.find('#hiddenDate');
var options = {};
options.minDate = new Date();
options.format = "yyyy-MM-dd";
options.autoclose = 'true';
displayInput.datepicker(options);
displayInput.datepicker().on('changeDate', function () {
//update the ng-model
var changedDate = displayInput.datepicker("getDate");
var newDate = converDateToDefault(changedDate);
if (scope.ngModel != newDate) {
scope.$apply(function () {
hiddenInput.val = newDate;
scope.ngModel = newDate;
});
}
});
scope.$watch("ngModel", function (newVal) {
if (typeof newVal !== undefined && newVal != null && newVal != "") {
displayInput.datepicker('destroy');
var option = {};
option.format = "yyyy-MM-dd";
displayInput.datepicker(option);
var convertedVal = converDateToDefault(displayInput.datepicker("getDate"));
if (convertedVal != "Invalid date" && newVal != convertedVal) {
displayInput.datepicker("setDate", convertDate(newVal));
hiddenInput.val = newVal;
}
}
}, true);
}
};
});
Thanks
Why reinvent the wheel? Use ui-bootstrap directive datepicker - http://angular-ui.github.io/bootstrap/#/datepicker
btw your original problem is because of
scope.$apply(function () {
hiddenInput.val = newDate;
scope.ngModel = newDate;
});
you can solve it by wrapping the scope.$apply
if (scope.$root.$$phase != '$apply' && scope.$root.$$phase != '$digest') {
scope.$apply(function () {
hiddenInput.val = newDate;
scope.ngModel = newDate;
});
}

Datepicker automatically hide on month or year select

I can go back from date to year in datepicker. But when I try to come back to date, when i clicked on year, datepicker automatically hide.
var datePickerOptions = this.data || {};
datePickerOptions.format = datePickerOptions.format || "mm-dd-yyyy";
datePickerOptions.language = datePickerOptions.language || this.lang.code;
var $context = this;
var dateContainer = this.container.find(".datepicker");
dateContainer.datepicker(datePickerOptions).on('changeDate', function (ev) {
// here i'm getting the value
});
This because of bootstrap-datepicker.js .
on click event you can find like following.
case 'span':
if (!target.is('.disabled')) {
this.viewDate.setUTCDate(1);
if (target.is('.month')) {
var day = 1;
var month = target.parent().find('span').index(target);
var year = this.viewDate.getUTCFullYear();
this.viewDate.setUTCMonth(month);
this._trigger('changeMonth', this.viewDate);
if (this.o.minViewMode === 1) {
this._setDate(UTCDate(year, month, day,0,0,0,0));
}
} else {
var year = parseInt(target.text(), 10)||0;
var day = 1;
var month = 0;
this.viewDate.setUTCFullYear(year);
this._trigger('changeYear', this.viewDate);
if (this.o.minViewMode === 2) {
this._setDate(UTCDate(year, month, day,0,0,0,0));
}
}
this.showMode(-1);
this.fill();
}
instead of this.fill(), if you use like following code, this will work as you expected.
if (target.is('.month')) {
if (!this._o.changeMonth) {
this.fill();
}
}
else {
if (!this._o.changeYear) {
this.fill();
}
}
I hope, this will help you. :-)

Categories

Resources