Creating a time range UI with angularjs and UI bootstrap - angularjs

I'm using a datepicker and two timepickers to create a time range within the given day (resulting in two date objects).
The datepicker's ng-model points to the start date and copies the date portion to the end date on ng-change. So far so good.
But: Modifying the end time reverts the end date to its original value!
Markup:
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.0.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/moment.min.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="TimepickerDemoCtrl">
<h1>Purpose: UI for a time range within a day</h1>
<p>Issue: Updating the date sets the correct end date BUT updating the end time reverts the end date back to its original value.</p>
<div class="input-group" style="width:150px">
<input type="text" required ng-model="item.startDate" ng-change="setEndDate()" class="form-control" datepicker-popup="yyyy-MM-dd" is-open="datePicker" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="openPicker($event, 'datePicker')"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
<timepicker ng-model="item.startDate" show-meridian="false"></timepicker>
<timepicker ng-model="item.endDate" show-meridian="false"></timepicker>
<pre class="alert alert-info">start is: {{item.startDate | date:'yyyy-MM-dd HH:mm' }}<br/>end is: {{item.endDate | date:'yyyy-MM-dd HH:mm' }}<br/>Duration: {{item.duration() | number:2}}</pre>
</div>
</body>
</html>
Script:
angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('TimepickerDemoCtrl', function ($scope, $log) {
var starttime = new Date();
starttime.setHours(8);
starttime.setMinutes(0);
var endtime = new Date();
endtime.setHours(17);
endtime.setMinutes(0);
$scope.item = {
startDate: starttime,
endDate: endtime,
duration: function () { return moment.duration(moment(this.endDate) - moment(this.startDate)).asHours() }
}
$scope.setEndDate = function() {
$scope.item.endDate.setDate($scope.item.startDate.getDate());
$scope.item.endDate.setMonth($scope.item.startDate.getMonth());
$scope.item.endDate.setFullYear($scope.item.startDate.getFullYear());
}
$scope.openPicker = function ($event, pickerInstance) {
$event.preventDefault();
$event.stopPropagation();
$scope[pickerInstance] = true;
};
});
http://plnkr.co/edit/zCFgf0mt4WOZeG9MPA9d

In some reason UI Bootstrap datepicker don't observe endDate value modification in your case.
Instead of modifying endDate you can copy startDate object and link to endDate:
$scope.setEndDate = function() {
$scope.item.endDate = angular.copy($scope.item.startDate);
};

Related

date format is not changing in angular js want to get in dd/mm/yyyy format in angular js

i have a date time data "11/12/2019 12:00:00 AM" , that i want to convert into 12/11/2019 in dd/mm/yyyy format but unable to change it.
<p>
{{data.DeviceTimeStamp | date : "dd.MM.y"}}
</p>
angular.module('myApp', [])
.controller("example", ["$scope", function(s) {
s.date = new Date();
}])
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.12/angular.min.js"></script>
<div ng-app="myApp">
<div class="container" ng-controller="example">
<div class="row">
<hr />
<div class="col-md-12">You landed here on {{date | date:'dd/MM/yyyy'}}, and I am in controller <code>example</code></div>
</div>
</div>
</div>
You can specify the array to contain the date inside an object and you can use this.
angular.module('myApp', [])
.controller("myCtrl", ["$scope", function(s) {
s.date = new Date('11/12/2019 12:00:00 AM');
}]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.12/angular.min.js"> </script>
<div ng-app="myApp">
<div ng-controller="myCtrl">
<div class="col-md-12">{{date | date:'dd/MM/yyyy'}}</div>
</div>
</div>
You can try like above.Here new Date() function parses your date string to a date object where it needs to be a valid input for date filter.
Hope it helps.
created custom filter
app.filter('parseDate', function () {
return function (input) {
return new Date(input);
};
});
then applied custom filter in my binding
<p>
{{ data.DeviceTimeStamp | parseDate | date:'d/M/yyyy' }}
</p>

Angular UI Bootstrap Datetimepicker with seconds

I want to get bootstrap datetimepicker input value in angularjs controller. I am using following custom directive to achieve this . But i am getting the value is undefined. I have added the code related to html and angular code related to the issue.
HTML
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.43/css/bootstrap-datetimepicker.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.2/locale/en-gb.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.43/js/bootstrap-datetimepicker.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular-resource.js"></script>
<div class="form-group">
<div class='input-group date' id='datetimepickerFrom' datetimepicker
ng-model="fromDate" >
<input type='text' class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
JS
'use strict';
var App = angular.module('app',['ngResource']);
App.directive('datetimepicker', function(){
return {
require: '?ngModel',
restrict: 'A',
link: function(scope, element, attrs, ngModel){
if(!ngModel) return; // do nothing if no ng-model
ngModel.$render = function(){
element.find('#datetimepickerFrom').val( ngModel.$viewValue || '' );
};
element.datetimepicker({
format : 'YYYY-MM-DD HH:mm:ss'
});
element.on('dp.change', function(){
scope.$apply(read);
});
read();
function read() {
var value = element.find('#datetimepickerFrom').val();
ngModel.$setViewValue(value);
console.log(ngModel.$setViewValue(value));
}
}
};
});
App.controller('myController', ['$scope', function($scope) {
$scope.fromDate = moment();
}]);
I have found a package for you to fix your problem which is in the link.
LINK
Easy way to achieve it follow these below steps
Add this markup.
You need to include the following scripts
//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js
//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.0.1.js
//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css
//cdn.rawgit.com/zhaber/datetimepicker/master/datetimepicker.js
//cdn.rawgit.com/zhaber/datetimepicker/master/datetimepicker.css
Controller will hold the model value in $scope.date which contains the date and time.
Update 1
This control does not support Seconds, I would suggest you to go with Angular UI Bootstrap as below
Include the above references expect last two and use the below markup.
<p class="input-group">
<input type="text" class="form-control" uib-datepicker-popup is-open="popup1.opened" ng-model="fromDate" datepicker-options="dateOptions" ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open1()"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
<div uib-timepicker ng-model="fromTime" ng-change="changed()" hour-step="1" minute-step="1" show-meridian="ismeridian" show-seconds="true"></div>
Add this module as a dependency ui.bootstrap
Use the below code to combine your value
$scope.changed = function () {
var month = $scope.fromDate.getMonth()+1;
var day = $scope.fromDate.getDate();
var year = $scope.fromDate.getFullYear();
var hour = $scope.fromTime.getHours();
if (hour < 10)
hour = "0"+hour;
var min = $scope.fromTime.getMinutes();
if (min < 10)
min = "0"+min;
var sec = $scope.fromTime.getSeconds();
if (sec < 10)
sec = "0"+sec;
//put it all togeter
var dateTimeString = month+'/'+day+'/'+year+' '+hour+':'+min+':'+sec;
$scope.fromDateTime= dateTimeString;
};
Your live ng-model value combined together
fromDateTime:{{fromDateTime |date : 'yyyy-MM-dd HH:mm:ss'}}
So by this if the seconds value is changed only you will get the actual Date Time

Odd behaviour with multiple datepickers using AngularJS and UI Bootstrap

I'm writing an app using AngularJS and UI Bootstrap, and I'm trying to implement a modal where the user can choose a start date and an end date for an event. The problem I'm having is that when the user is chosing an end date, the start date is affected as well, leading to incorrect values.
I have made a minimal test case here: http://147.75.205.135/test/
(I tried to reproduce it using Plunkr, but for some reason I didn't get the same behaviour there)
Plunker link: http://plnkr.co/edit/kika1viHi8csXMuklw8Z
To recreate the issue, click the "Launch" button, open up the datepicker for the start date, and click the right arrow to go to the next month and choose a date. Then for the end date, click the right arrow to go to the next month and pick any date. Then click "Save". An alert box will show up displaying the start and end date, but the start date does not correspond to the one chosen in the datepicker, it is set to the 1st of the month chosen for the end date.
I have nailed it down to the following function in http://147.75.205.135/test/script/angular/main.js:
$scope.adjustEndDate = function() {
if ($scope.endDate < $scope.startDate) {
console.log("Adjusting end date to " + $scope.startDate);
$scope.endDate = $scope.startDate;
}
};
It is called from ng-change on the start date picker. Commenting it out makes the odd behaviour go away. But I don't understand why it would cause this issue. I need this function so that when the user has chosen a start date, the end date is automatically adjusted so that it is never before the start date.
Complete code:
index.html
<!doctype html>
<html>
<head>
<title>Test page</title>
<link rel="stylesheet" href="bootswatch-dist/css/bootstrap.min.css"></link>
<link rel="stylesheet" href="css/main.css"></link>
<script>
var conf = {
templates: {
datepickModal: "script/angular/templates/datepickModal.html"
}
};
</script>
<script src="angular/angular.js" ></script>
<script src="jquery/dist/jquery.min.js"></script>
<script src="angular-animate/angular-animate.js"></script>
<script src="angular-bootstrap/ui-bootstrap.js"></script>
<script src="angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script src="script/angular/main.js"></script>
</head>
<body data-ng-app="mainApp">
<div id="main" ng-controller="testCtrl">
<button ng-click="openModal()">Launch modal</button>
</div>
</body>
</html>
main.js
+function(angular, d3) {
"use strict";
var app = angular.module('mainApp', ['ui.bootstrap']);
app.controller('datepickCtrl', ['$scope', '$rootScope', '$uibModalInstance', function($scope, $rootScope, $uibModalInstance) {
$scope.startDate = new Date();
$scope.endDate = new Date();
$scope.startOpened = false;
$scope.endOpened = false;
$scope.name = '';
$scope.mode = 'list';
$scope.save = function () {
alert("Saving dates start: " + $scope.startDate + " and end " + $scope.endDate);
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
$scope.toggleStartCalendar = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.startOpened = !$scope.startOpened;
};
$scope.toggleEndCalendar = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.endOpened = !$scope.endOpened;
};
$scope.dateOptions = {
formatYear: 'yy',
startingDay: 1
};
$scope.setMode = function(mode) {
$scope.mode = mode;
}
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
$scope.adjustEndDate = function() {
if ($scope.endDate < $scope.startDate) {
console.log("Adjusting end date to " + $scope.startDate);
$scope.endDate = $scope.startDate;
}
};
$scope.adjustStartDate = function() {
if ($scope.startDate > $scope.endDate) {
console.log("Adjusting start date to " + $scope.endDate);
$scope.startDate = $scope.endDate;
}
};
}]);
app.controller('testCtrl', ['$scope', '$rootScope', '$uibModal', function($scope, $rootScope, $uibModal) {
$scope.openModal = function() {
if (conf.suspended) {
return;
}
var modalInstance = $uibModal.open({
animation: true,
templateUrl: conf.templates.datepickModal,
controller: 'datepickCtrl',
size: 'md'
});
};
}]);
}(window.angular, window.d3);
modal.html
<div class="modal-header">
<h3 class="modal-title">Datepick tester</h3>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-6">
<p class="input-group">
<label for="startdate">Start date</label><p class="input-group">
<input type="text" class="form-control" uib-datepicker-popup ng-model="startDate" ng-change="adjustEndDate()" is-open="startOpened" ng-required="true" uib-datepicker-options="dateOptions" name="startdate" ng-click="toggleStartCalendar($event)"/>
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="toggleStartCalendar($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
<div class="col-md-6">
<p class="input-group">
<label for="enddate">End date</label><p class="input-group">
<input type="text" class="form-control" uib-datepicker-popup ng-model="endDate" is-open="endOpened" ng-change="adjustStartDate()" ng-required="true" uib-datepicker-options="dateOptions" name="enddate" ng-click="toggleEndCalendar($event)"/>
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="toggleEndCalendar($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="save()">Save</button>
<button class="btn btn-warning" ng-click="cancel()">Close</button>
</div>
Versions used
AngularJS: 1.4.8
JQuery: 2.1.4
UI-bootstrap: 1.2.4
I had the same problem. The issue is that you are copying the Date object here:
$scope.endDate = $scope.startDate
Just change it to:
$scope.endDate = new Date($scope.startDate.getTime())

AngularJS & UI Bootstrap(DatePicker) - After date selection, the ngModel will not keep the UTC timestamp

Using:
UI Bootstrap datePicker component (ver. 0.13.4)
AngularJS (ver 1.4.5)
I'm trying to format the binded ngModel value of the user selected date, so I can pass the value as a UTC timestap via $http
Here is my HTML
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<script src="ui-bootstrap-tpls-0.13.4.js"></script>
<script src="app.js"></script>
</head>
<body ng-app="formApp" ng-controller="formController">
<p>Selected date is: {{ formData.dt | date:'fullDate' }}</p>
<p>The binded ngModel is: {{ formData.dt }}</p>
<div style="display:inline-block; min-height:290px;">
<datepicker
ng-model="formData.dt"
min-date="minDate"
max-date="maxDate"
show-weeks="false"
starting-day = "1"
class="">
</datepicker>
</div>
</body>
</html>
here is the Controller
var app = angular.module('formApp', ['ui.bootstrap'])
app.controller('formController', function($scope, $http) {
$scope.formData = {};
var date = new Date();
$scope.formData.dt = date.getTime();
});
and here is a Plunker demo - http://plnkr.co/edit/3vKIO3187ZC2FAnlw2ZW?p=preview
As you will see, selecting any date in the picker changes the model format.
How can I set it so when any date is selected, it still has a UTC value?
You have to create your own $parser inside a directive to format the date value how you want it to be formatted.
app.directive('dateAsMs', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope,elem,attrs,ngModelCtrl) {
ngModelCtrl.$parsers.push(function(value){
if (value && value.getTime) {
return value.getTime();
} else {
return value;
}
});
}
};
});
And then add the attribute date-as-ms to your datepicker element
Here is your modified plnkr: http://plnkr.co/edit/0V3CkLt8Gjtwc9Jj3zxE?p=preview

Angular UI Bootstrap datepicker malfunctioning

I am using Angular Ui Datepicker in my app. Strange thing is happening, may be a bug. The date picker is not functioning (not showing) if there is a child element inside the datepicker element.
In my example below if I put span (or any other) tag inside a tag - where I have put my datepicker - it will not work, but if there is not child element inside of it , it works as expected.
Is this a bug or I am missing something ?
Edit : Created A Fiddle Also
var app = angular.module('app', ['ui.bootstrap']);
app.controller("TestController", function($scope) {
$scope.isOpen = false;
$scope.isOpen2 = false;
$scope.isOpen3 = false;
$scope.popupOptions = {};
});
<link href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet" />
<div ng-app="app">
This will show Date picker
<br />
<a href="javascript://" ng-model="deadline2" is-open="isOpen2" ng-click="isOpen2 = !isOpen2" datepicker-popup="popupOptions"> <span> This will not </span>
</a>
<br />
<a href="javascript://"> <span ng-model="deadline2" is-open="isOpen3" datepicker-popup="popupOptions" ng-click="isOpen3 = !isOpen3"> This will also show </span>
</a>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.min.js"></script>
Looks like the datepicker can only be set on the innermost elements. It might be that way by design as I found no examples where datepicker is set on a parent element.
Also, you code works if the datepicker is set on span(or any other child element).
<a href="javascript://">
<span ng-model="deadline" is-open="isOpen" ng-click="isOpen = !isOpen" datepicker-popup="popupOptions">datepicker set on span inside anchor</span>
</a>
Plnkr
Here is an example to use the directive with a bootstrap input, displaying a calendar button
HTML
<p class="input-group">
<input type="text" class="form-control" datetime-picker="dd MMM yyyy HH:mm" ng-model="myDate" is-open="isOpen" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="openCalendar($event, prop)"><i class="fa fa-calendar"></i></button>
</span>
</p>
JAVASCRIPT
app.controller('MyController', function() {
var that = this;
this.isOpen = false;
this.openCalendar = function(e) {
e.preventDefault();
e.stopPropagation();
that.isOpen = true;
};
});
See demo : https://github.com/Gillardo/bootstrap-ui-datetime-picker

Resources