Angularjs input string to time format - javascript

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.

Related

angular bootstrap datepicker get visible dates (day mode)

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.

Angular JS dual input Directive UpDate View Value

Hi I have a situation here,
I have created a dual input directive. Can you please help to in the below scenario.
When I change the model value via controller to undefined, the view values are not cleared. Here is the Codes,
My Dual Input Directive is as follows,
angular.module("awcQuoteBuy.directives")
.directive('dualInput', function($timeout, inputValidationService) {
return {
restrict: 'E',
templateUrl: 'app/partials/common/doubleInput.html',
scope: {
modelValue: '=',
size: '#',
fieldError: '#',
blurFn: '&loseFocus'
},
link: function postLink(scope, element, attrs, ctrl) {
scope.leftFocused = false;
scope.rightFocused = false;
scope.$watch('left', function(newVal, oldVal) {
if (newVal!==oldVal) {
var tmp = (newVal) ? inputValidationService.formatNumber(newVal+'') : '';
scope.modelValue = tmp + '|'+ scope.getOtherValue(scope.right);
}
});
scope.$watch('right', function(newVal, oldVal) {
if (newVal!==oldVal) {
var tmp = (newVal) ? inputValidationService.formatNumber(newVal+'') : '';
scope.modelValue = scope.getOtherValue(scope.left) + '|' + tmp;
}
});
scope.getOtherValue = function(value) {
return (value && value!=='') ? inputValidationService.formatNumber(value+'') : '';
};
//will set the value initially
$timeout(function() {
if (!scope.modelValue || scope.modelValue===null) {
scope.modelValue = '';
}
if (scope.modelValue!=='') {
var splitIndex = scope.modelValue.indexOf('|');
if (splitIndex>=0) {
var values = scope.modelValue.split('|');
scope.left = values[0];
scope.right = values[1];
} else {
scope.left = scope.modelValue;
}
}
});
/*
Below functions will add on-blur (lose focus) support to both fields.
*/
scope.focusLeft = function() {
scope.leftFocused = true;
};
scope.blurLeft = function() {
scope.leftFocused = false;
$timeout(function() {
if (!scope.rightFocused) {
scope.blurFn();
}
}, 100);
};
scope.focusRight = function() {
scope.rightFocused = true;
};
scope.blurRight = function() {
scope.rightFocused = false;
$timeout(function() {
if (!scope.leftFocused) {
scope.blurFn();
}
}, 100);
};
}
};
});
The HTML Piece of code is as follows,
<dual-input model-value="dualInput[$index]" ng-switch-when="DUAL_NUMBER" size="{{q.length}}"
field-error="{{q.invalid || (nextClicked && !validateGeneralQuestion(acc.memberId, q))}}" id="{{'gQDual'+$index}}"
lose-focus="saveGeneralAnswer(acc.memberId, q)"></dual-input>
In My Controller when I set the scope value to undefined or null, the entered values in the view is not cleared. Please help me here what I should do to clear this value
$scope.dualInput[$index]=undefined;
The directive itself has got the auto initialize feature. So I had to re render the directive whenever I wanted to reinitialize.
If you want to explicitly update user ctrl.$setViewvalue = ""

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);
}
};

Angular js directive doesn't work on page load

I am new to angularjs the below directive is to support decimal and commas, it works fine when a change is made to the field how ever the data in the fields are not validated when the page loads
var app = angular.module('myApply.directives', [], function () {
});
app.directive('numericDecimalInput', function($filter, $browser, $locale,$rootScope) {
return {
require: 'ngModel',
priority: 1,
link: function($scope, $element, $attrs, ngModelCtrl) {
var replaceRegex = new RegExp($locale.NUMBER_FORMATS.GROUP_SEP, 'g');
var fraction = $attrs.fraction || 0;
var listener = function() {
var value = $element.val().replace(replaceRegex, '');
$element.val($filter('number')(value, fraction));
};
var validator=function(viewValue) {
ngModelCtrl.$setValidity('outOfMax', true);
ngModelCtrl.$setValidity(ngModelCtrl.$name+'Numeric', true);
ngModelCtrl.$setValidity('rangeValid', true);
if(!_.isUndefined(viewValue))
{
var newVal = viewValue.replace(replaceRegex, '');
var newValAsNumber = newVal * 1;
// check if new value is numeric, and set control validity
if (isNaN(newValAsNumber)) {
ngModelCtrl.$setValidity(ngModelCtrl.$name + 'Numeric', false);
} else
{
if (newVal < 0) {
ngModelCtrl.$setValidity(ngModelCtrl.$name + 'Numeric', false);
}
else {
newVal = newValAsNumber.toFixed(fraction);
ngModelCtrl.$setValidity(ngModelCtrl.$name + 'Numeric', true);
if (!(_.isNull($attrs.maxamt) || _.isUndefined($attrs.maxamt))) {
var maxAmtValue = Number($attrs.maxamt) || Number($scope.$eval($attrs.maxamt));
if (newVal > maxAmtValue) {
ngModelCtrl.$setValidity('outOfMax', false);
} else {
ngModelCtrl.$setValidity('outOfMax', true);
}
if(!(_.isNull($attrs.minamt) || _.isUndefined($attrs.minamt)))
{
var minAmtValue = Number($attrs.minamt)|| Number($scope.$eval($attrs.minamt));
if((newVal > maxAmtValue) || (newVal < minAmtValue)){
ngModelCtrl.$setValidity('rangeValid', false);
}
else
{
ngModelCtrl.$setValidity('rangeValid', true);
}
}
}
else if((!(_.isNull($attrs.minamt) || _.isUndefined($attrs.minamt))))
{
var minAmtValue = Number($attrs.minamt)|| Number($scope.$eval($attrs.minamt));
if(newVal < minAmtValue)
{
ngModelCtrl.$setValidity('outOfMin', false);
}
else
{
ngModelCtrl.$setValidity('outOfMin', true);
}
}
else {
ngModelCtrl.$setValidity('outOfMax', true);
}
}
}
return newVal;
}
};
// This runs when the model gets updated on the scope directly and keeps our view in sync
ngModelCtrl.$render = function() {
ngModelCtrl.$setValidity('outOfMax', true);
ngModelCtrl.$setValidity(ngModelCtrl.$name+'Numeric', true);
$element.val($filter('number')(ngModelCtrl.$viewValue, fraction));
};
$element.bind('change', listener);
$element.bind('keydown', function(event) {
var key = event.keyCode;
// If the keys include the CTRL, SHIFT, ALT, or META keys, home, end, or the arrow keys, do nothing.
// This lets us support copy and paste too
if (key == 91 || (15 < key && key < 19) || (35 <= key && key <= 40))
return;
});
$element.bind('paste cut', function() {
$browser.defer(listener);
});
ngModelCtrl.$parsers.push(validator);
ngModelCtrl.$formatters.push(validator);
}
};
});
Could some one please let me know as what I am missing .
Thanking you in advance.
Have you declared your app (doesn't show this in your code)? ie:
var app = angular.module('app', []);
Do you have ng-app in your HTML document anywhere?
<html lang="en-GB" ng-app="app">
Check out the documentation to get started with modules (Angular is very well documented, well worth reading): https://docs.angularjs.org/guide/module
app.directive('numericDecimalInput', function($filter, $browser, $locale,$rootScope) {
return {
require: 'ngModel',
priority: 1,
link: function($scope, $element, $attrs, ngModelCtrl) {
...
validator($element.val());
}
};
});

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;
});
}

Categories

Resources