Angularjs datetime-picker timezone - javascript

I am using angular-material-datetimepicker in my modal to enter date and time. However, angular sends all data server side in json and that changes the time to UTC. On reloading my client side, UTC time is displayed which I do not want. How do I make the client display my local time (GMT +2 in my case)? How do I manipulate only the date part of the json string? I've seen confusing solutions on other similar SO q's and forums. Thanks.
On the modal html
<div class="time">
<md-input-container class="md-input-has-placeholder start_time">
<label>Start Date/Time</label>
<input mdc-datetime-picker="" date="true" time="true" type="text" id="datetime" placeholder="Start" min-date="date" format="DD/MM/YYYY hh:mm" ng-model="Project.StartAt" class=" md-input">
</md-input-container>
<md-input-container class="md-input-has-placeholder endtime">
<label>End Date/Time</label>
<input mdc-datetime-picker="" date="true" time="true" type="text" id="datetime" placeholder="End" min-date="date" format="DD/MM/YYYY hh:mm" ng-model="Project.EndAt" class=" md-input">
</md-input-container>
</div>
angular
$scope.editProject = function(data) {
$scope.showSelected = true;
$scope.SelectedProject = data;
var fromDate = moment(data.start).format('DD/MM/YYYY LT');
var endDate = moment(data.end).format('DD/MM/YYYY LT');
$scope.Project = {
ProjectID : data.projectID,
Client : data.client,
Title : data.title,
Description: data.description,
Employees: data.employees,
StartAt : fromDate,
EndAt : endDate,
IsFullDay : false
}
$scope.ShowModal()
},
$scope.ShowModal = function(){
$scope.option = {
templateUrl: 'modalContent.html',
controller: 'modalController',
controllerAs: '$ctrl',
backdrop: 'static',
resolve: {
Project : function () {
return $scope.Project;
},
SelectedProject : function () {
return $scope.SelectedProject;
},
projects: function () {
return $ctrl.projects;
}
}
};
var modal = $uibModal.open($scope.option);
modal.result.then(function (data) {
$scope.Project = data.project;
switch (data.operation){
case 'Save':
//Save here
$http({
method: 'POST',
url: '/',
data: $scope.Project
}).then(function(response){
if(response.data.status){
$scope.projects.push(Project);
}
})
break;

You can apply filter for that like :
$scope.yourDate= $filter('date')(new Date($scope.yourDate), 'yyyy-MM-dd'); // Try different format as per your requirement
Don't forget to inject dependency $filter.

Related

API, angularJS, to get datas

I never done angularJS from all my life and i am lost.
So i have done this file, to obtain datas from an api with a filter of time.
forecast.js
(function() {
angular.module('application').factory('Forecast', ['$http', '$q', function($http, $q){
var ApiAddr = "api.com/";
forecast.getResults = function(timeStart, timeEnd){
// We map application varaible names with API param names
var httpParams = {
type: "global",
time: "minute",
tsmin: timeStart,
tsmax: timeEnd
};
return $http.get(apiAddr, {
params: httpParams,
cache: true
}).then(function(data){
return data;
},
function(response){
console.log(
"HTTP request "+ApiAddr+
" (with parameters tsmin="+httpParams.tsmin+", tsmax="+httpParams.tsmax+
", type="+httpParams.type+", time="+httpParams.time+
(httpParams.motive ? ", motive="+httpParams.motive : "")+
(httpParams.vector ? ", vector="+httpParams.vector : "")+
(httpParams.media ? ", media="+httpParams.media : "")+
") failed with "+response.status
);
return $q.reject(response);
}
);
}];
But i have no idea to make a controller adapter to this. What type of controller i can do ?
Every exemple are based on a fixed json file, with no parameters.
Moreover, i want, in HTML to imput the time filter, but i have totaly no idea of what to do for this. The example i have seen were to get datas, no to send.
Ps : I have made 2 days of research about this, i have never done front end programming in my life.
(function() {
angular.module('application', [])
.factory('Forecast', ['$http', '$q', function($http, $q) {
var apiaddress = 'api.com';
var forecast = {};
forecast.getResults = function(timeStart, timeEnd) {
// We map application varaible names with API param names
var httpParams = {
type: "global",
time: "minute",
tsmin: timeStart,
tsmax: timeEnd
};
return $http.get(apiaddress, {
params: httpParams,
cache: true
}).then(function(result) {
return result.data;
});
};
return forecast;
}])
.controller('SampleCtrl', ['$scope', 'Forecast', function($scope, Forecast) {
$scope.forecastReport = '';
$scope.getForecast = function() {
Forecast.getResults($scope.timeStart, $scope.timeEnd)
.then(function(report) {
$scope.result = report;
}).catch(function(err) {
$scope.result = '';
console.error('Unable to fetch forecast report: ' + err);
});
};
}]);
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="application" ng-controller="SampleCtrl">
<label>Time Start:
<input type="text" ng-model="timeStart"/></label>
<label>Time End:
<input type="text" ng-model="timeEnd"/></label>
<button ng-click="getForecast()">Get Forecast</button>
<hr/>
<div>
<b>Forecast Result:</b>
</div>
<pre>{{forecastReport | json}}</pre>
</div>
Just inject the factory into your controller like this:
var app = angular.module('application');
app.controller('myController',
['$scope', 'Forecast', function($scope, Forecast) { /* access to Forecast*/}]);
Or with a component (cleaner):
app.component('myComponentCtrl', {
templateUrl: 'template.html'
controller: myComponentCtrl
})
myComponentCtrl.$inject = ['$scope', 'Forecast'];
function myComponentCtrl($scope, Forecast) {/* ... */ }

bootstrap-datepicker (range) - AngularJS Directive

I'm trying to make use of the bootstrap-datepicker.
I have an existing AngularJS directive, but when setting the initial value, it does not update when making use of a date range.
HTML
<div class="input-group input-daterange" id="fromToDate" calendar ng-model="vm.fromToDate">
<input type="text" class="form-control input-sm" required ng-model="vm.bookingFromDate">
<span class="input-group-addon">to</span>
<input type="text" class="form-control input-sm" required ng-model="vm.bookingToDate">
</div>
Directive
// this directive updates the value, once it has been selected, but not when the initial value has been set**
function calendar() {
return {
require: 'ngModel',
link: function($scope, el, attr, ngModel) {
$(el)
.datepicker({
autoclose: true,
todayHighlight: true,
todayBtn: 'linked',
onSelect: function(dateText) {
$scope.$apply(function() {
ngModel.$setViewValue(dateText);
});
}
});
}
};
};
Then, I tried the following directive (found here), but this doesn't work either for a date range - instead:
function calendar() {
return {
require: '?ngModel',
restrict: 'A',
link: function ($scope, element, attrs, controller) {
var updateModel, onblur;
if (controller != null) {
updateModel = function (event) {
element.datepicker('hide');
element.blur();
};
onblur = function () {
var date = element.val();
return $scope.$apply(function () {
return controller.$setViewValue(date);
});
};
controller.$render = function() {
var date = controller.$viewValue;
element.datepicker().data().datepicker.date = date.from.toDate();
element.datepicker('setValue');
element.datepicker('update');
return controller.$viewValue;
};
}
return attrs.$observe('bdatepicker', function (value) {
var options = {
format: "yyyy/mm/dd",
todayBtn: "linked",
autoclose: true,
todayHighlight: true
};
return element.datepicker(options).on('changeDate', updateModel).on('blur', onblur);
});
}
};
};
Any assistance would be appreciated!
Thanks!
[Update]
CodePen to illustrate the issue:
<p data-height="322" data-theme-id="dark" data-slug-hash="BLkagb" data-default-tab="js,result" data-user="Programm3r" data-embed-version="2" class="codepen">See the Pen Bootstrap-Datepicker (Range) AngularJS by Richard (#Programm3r) on CodePen.</p>
<script async src="//assets.codepen.io/assets/embed/ei.js"></script>
You could use the following library to solve the issue. datepicker
Edit: to resolve disappearance of date.
<input type="text" class="form-control input-sm" ng-model="vm.bookingFromDate" id="fromDate">
<span class="input-group-addon">to </span>
<input type="text" class="form-control input-sm" ng-model="vm.bookingToDate" id="toDate">
in controller
$('#fromDate').val(vm.bookingFromDate);
$('#toDate').val(vm.bookingToDate);

How to set datepicker minDate?

I have a directive date-picker.js and view as selectDate.html. I want to set minDate for the date picker when the value of another datepicker changes. How to achieve that?
.directive('selectDate', ['moment', function(moment) {
return {
restrict: 'E',
require:'^ngModel',
templateUrl: 'views/selectDate.html',
replace: true,
scope: {
ngModel: '='
},
link: function($scope, element, attrs) {
$scope.date = $scope.ngModel;
$scope.dateOptions = {
startingDay: 1,
showWeeks: false
};
$scope.dateStatus = {
opened: false
};
$scope.openDatePopup = function() {
$scope.dateStatus.opened = true;
};
$scope.$watch('date', function (newValue, oldValue) {
if (newValue !== oldValue) {
var date = moment(newValue);
$scope.ngModel = date.format('YYYY-MM-DD');
}
});
}
};
selectDate.html
<span class="select-date">
<input type="text" readonly="readonly" datepicker-popup="dd.MM.yyyy" datepicker-options="{startingDay: 1, showWeeks: true}" ng-model="date" show-button-bar="false" current-text="Heute" close-text="Schließen" is- open="dateStatus.opened" min-date="'2014-01-01'" class="form-control" required="required" ng-click="openDatePopup()">
</span>
I am using it like below:
From <select-date ng-model="fromDate"></select-date>
To <select-date ng-model="toDate"></select-date>
I want to set minDate of toDate to fromDate value.
Well you can user ui-bootstrap directive which is lot easier,below is the code
$scope.dateOptions = {
formatYear: 'yyyy',
startingDay: 1
};
$scope.opened = true;
$scope.minDate= new Date();
var maxDate = new Date();
maxDate.setFullYear (maxDate.getFullYear() + 2);//enable for 2 future years..
$scope.maxDate= maxDate;
Your HTML will look like this
<input type="text" class="form-control selection-box"
id="datepicker"
datepicker-popup="{{dateFormat}}"
ng-model="selectedDate" is-open="opened"
ng-class="{'date-changed':colorChange[$parent.$parent.$index +'-'+ $parent.$index]}"
min-date="minDate" max-date="maxDate"
datepicker-options="dateOptions" readonly="readonly"
ng-change="changeDate()"
close-text="Close" ng-required="true" />
To answer OP's question you can have following code changes.
From <select-date ng-model="fromDate" min-date="fromMinDate"></select-date>
To <select-date ng-model="toDate" min-date="toMinDate"></select-date>
<span class="select-date">
<input type="text" readonly="readonly" datepicker-popup="dd.MM.yyyy" datepicker-options="{startingDay: 1, showWeeks: true}" ng-model="date" show-button-bar="false" current-text="Heute" close-text="Schließen" is- open="dateStatus.opened" min-date="setMinDate" class="form-control" required="required" ng-click="openDatePopup()">
</span>
Below are changes in your directive.
.directive('selectDate', ['moment', function(moment) {
return {
restrict: 'E',
require:'^ngModel',
templateUrl: 'views/selectDate.html',
replace: true,
scope: {
ngModel: '='
minDate: '#'//which date input we are changing...
},
link: function($scope, element, attrs) {
$scope.date = $scope.ngModel;
$scope.selectedDateType = $scope.minDate=='fromMinDate'?'From':'To';
$scope.dateOptions = {
startingDay: 1,
showWeeks: false
};
$scope.dateStatus = {
opened: false
};
$scope.openDatePopup = function() {
$scope.dateStatus.opened = true;
$scope.setMinDate = new Date();//for From date..
};
$scope.$watch('date', function (newValue, oldValue) {
if (newValue !== oldValue) {
var date = moment(newValue);
$scope.ngModel = date.format('YYYY-MM-DD');
if($scope.selectedDateType=='From'){
$scope.setMinDate = $scope.fromDate;//for To date
}
}
});
}
};

Data from form are not passed to submit function - Using Angular

I have a problem with a form implemented using Angular.
defining my variable in the scope I can see value (pre-filled) in the html form (ng-model), but when I submit the function, the new data (inserted by the users) don't update the model ($scope var) in the controller.
Here a snipped of my html and js controller:
<form class="form-horizontal">
<h3>Citizen</h3>
<div class="row">
<div class="form-group">
<label for="name" class="col-sm-2 control-label">Name</label>
<div class="col-sm-4">
<input type="text" class="form-control" id="name" ng-model="ticketDetails.ticketDetails.name" placeholder="Name">
</div>
<label for="DOB" class="col-sm-2 control-label">Birth date</label>
<div class="col-sm-4">
<input type="date" class="form-control" id="DOB" ng-model="ticketDetails.ticketDetails.DOB" placeholder="Birth Date">
</div>
</div>
</div>...
and the controller
angular.module('demoApp', [])
.controller('mainController', function($scope, $http) {
// $scope.ticketDetails = { "ticketDetails" : {
// "name": "Giovanni Vigorelli",
// "DOB": "1974-05-02T05:07:13Z",
// "driverLicense": "e345234",
// "registration": "hdd843",
// "ticketType": "Speeding",
// "date": "2016-05-02T05:07:13Z",
// "location": "34 Queen St, Auckland",
// "ticketId": "12345",
// "officer": "Oscar Nice"
// }};
$scope.ticketDetails = { "ticketDetails": {}};
$scope.ticketDetails.ticketDetails.ticketId = (+new Date).toString(36).slice(-5);
// The following should be the authentucated user
$scope.ticketDetails.ticketDetails.officer = "Oscar Nice";
var bpmQueryParam = 'action=start&bpdId=25.c1206b63-1e94-4aaa-9dc1-76363270b441&processAppId=2066.d0e91cc6-a515-4965-ba6f-516bdbddcb00&params=' + JSON.stringify($scope.ticketDetails) + '&parts=all';
$scope.startProcess = function(){
console.log('### In startProcess');
console.log("### bpmQueryParam: " + bpmQueryParam);
var req = {
method: 'POST',
headers: {'Authorization': 'Basic YWRtaW46YWRtaW4=','Accept': 'application/json','Access-Control-Allow-Origin': '*', 'Content-Type': 'application/x-www-form-urlencoded'},
url: 'http://1.1.1.1:9080/rest/bpm/wle/v1/process',
data: bpmQueryParam
}
Basically I don't a bidirectional sync of the var, just from controller to view and NOT from view to controller.
Any advice?
Cheers, Giovanni
I suppose $scope.startProcess is your submit function. Please write the following line inside the submit function:
var bpmQueryParam = 'action=start&bpdId=25.c1206b63-1e94-4aaa-9dc1-76363270b441&processAppId=2066.d0e91cc6-a515-4965-ba6f-516bdbddcb00&params=' + JSON.stringify($scope.ticketDetails) + '&parts=all';
You have wriiten this code outside the function, therefore it is taking the initial data for $scope.ticketDetails variable.
You should write it as following:
$scope.startProcess = function(){
var bpmQueryParam = 'action=start&bpdId=25.c1206b63-1e94-4aaa-9dc1-76363270b441&processAppId=2066.d0e91cc6-a515-4965-ba6f-516bdbddcb00&params=' + JSON.stringify($scope.ticketDetails) + '&parts=all';
// Rest of your code
}

Angularjs how to upload multipart form data and a file?

I'm a beginner to angular.js but I have a good grasp of the basics.
What I am looking to do is upload a file and some form data as multipart form data. I read that this isn't a feature of angular, however 3rd party libraries can get this done. I've cloned angular-file-upload via git, however I am still unable to post a simple form and a file.
Can someone please provide an example, html and js of how to do this?
First of all
You don't need any special changes in the structure. I mean: html input tags.
<input accept="image/*" name="file" ng-value="fileToUpload"
value="{{fileToUpload}}" file-model="fileToUpload"
set-file-data="fileToUpload = value;"
type="file" id="my_file" />
1.2 create own directive,
.directive("fileModel",function() {
return {
restrict: 'EA',
scope: {
setFileData: "&"
},
link: function(scope, ele, attrs) {
ele.on('change', function() {
scope.$apply(function() {
var val = ele[0].files[0];
scope.setFileData({ value: val });
});
});
}
}
})
In module with $httpProvider add dependency like ( Accept, Content-Type etc) with multipart/form-data. (Suggestion would be, accept response in json format)
For e.g:
$httpProvider.defaults.headers.post['Accept'] = 'application/json, text/javascript';
$httpProvider.defaults.headers.post['Content-Type'] = 'multipart/form-data; charset=utf-8';
Then create separate function in controller to handle form submit call.
like for e.g below code:
In service function handle "responseType" param purposely so that server should not throw "byteerror".
transformRequest, to modify request format with attached identity.
withCredentials : false, for HTTP authentication information.
in controller:
// code this accordingly, so that your file object
// will be picked up in service call below.
fileUpload.uploadFileToUrl(file);
in service:
.service('fileUpload', ['$http', 'ajaxService',
function($http, ajaxService) {
this.uploadFileToUrl = function(data) {
var data = {}; //file object
var fd = new FormData();
fd.append('file', data.file);
$http.post("endpoint server path to whom sending file", fd, {
withCredentials: false,
headers: {
'Content-Type': undefined
},
transformRequest: angular.identity,
params: {
fd
},
responseType: "arraybuffer"
})
.then(function(response) {
var data = response.data;
var status = response.status;
console.log(data);
if (status == 200 || status == 202) //do whatever in success
else // handle error in else if needed
})
.catch(function(error) {
console.log(error.status);
// handle else calls
});
}
}
}])
<script src="//unpkg.com/angular/angular.js"></script>
This is pretty must just a copy of that projects demo page and shows uploading a single file on form submit with upload progress.
(function (angular) {
'use strict';
angular.module('uploadModule', [])
.controller('uploadCtrl', [
'$scope',
'$upload',
function ($scope, $upload) {
$scope.model = {};
$scope.selectedFile = [];
$scope.uploadProgress = 0;
$scope.uploadFile = function () {
var file = $scope.selectedFile[0];
$scope.upload = $upload.upload({
url: 'api/upload',
method: 'POST',
data: angular.toJson($scope.model),
file: file
}).progress(function (evt) {
$scope.uploadProgress = parseInt(100.0 * evt.loaded / evt.total, 10);
}).success(function (data) {
//do something
});
};
$scope.onFileSelect = function ($files) {
$scope.uploadProgress = 0;
$scope.selectedFile = $files;
};
}
])
.directive('progressBar', [
function () {
return {
link: function ($scope, el, attrs) {
$scope.$watch(attrs.progressBar, function (newValue) {
el.css('width', newValue.toString() + '%');
});
}
};
}
]);
}(angular));
HTML
<form ng-submit="uploadFile()">
<div class="row">
<div class="col-md-12">
<input type="text" ng-model="model.fileDescription" />
<input type="number" ng-model="model.rating" />
<input type="checkbox" ng-model="model.isAGoodFile" />
<input type="file" ng-file-select="onFileSelect($files)">
<div class="progress" style="margin-top: 20px;">
<div class="progress-bar" progress-bar="uploadProgress" role="progressbar">
<span ng-bind="uploadProgress"></span>
<span>%</span>
</div>
</div>
<button button type="submit" class="btn btn-default btn-lg">
<i class="fa fa-cloud-upload"></i>
<span>Upload File</span>
</button>
</div>
</div>
</form>
EDIT: Added passing a model up to the server in the file post.
The form data in the input elements would be sent in the data property of the post and be available as normal form values.
It is more efficient to send the files directly.
The base64 encoding of Content-Type: multipart/form-data adds an extra 33% overhead. If the server supports it, it is more efficient to send the files directly:
Doing Multiple $http.post Requests Directly from a FileList
$scope.upload = function(url, fileList) {
var config = {
headers: { 'Content-Type': undefined },
transformResponse: angular.identity
};
var promises = fileList.map(function(file) {
return $http.post(url, file, config);
});
return $q.all(promises);
};
When sending a POST with a File object, it is important to set 'Content-Type': undefined. The XHR send method will then detect the File object and automatically set the content type.
Working Demo of "select-ng-files" Directive that Works with ng-model1
The <input type=file> element does not by default work with the ng-model directive. It needs a custom directive:
angular.module("app",[]);
angular.module("app").directive("selectNgFiles", function() {
return {
require: "ngModel",
link: function postLink(scope,elem,attrs,ngModel) {
elem.on("change", function(e) {
var files = elem[0].files;
ngModel.$setViewValue(files);
})
}
}
});
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app">
<h1>AngularJS Input `type=file` Demo</h1>
<input type="file" select-ng-files ng-model="fileList" multiple>
<h2>Files</h2>
<div ng-repeat="file in fileList">
{{file.name}}
</div>
</body>
You can check out this method for sending image and form data altogether
<div class="form-group ml-5 mt-4" ng-app="myApp" ng-controller="myCtrl">
<label for="image_name">Image Name:</label>
<input type="text" placeholder="Image name" ng-model="fileName" class="form-control" required>
<br>
<br>
<input id="file_src" type="file" accept="image/jpeg" file-input="files" >
<br>
{{file_name}}
<img class="rounded mt-2 mb-2 " id="prvw_img" width="150" height="100" >
<hr>
<button class="btn btn-info" ng-click="uploadFile()">Upload</button>
<br>
<div ng-show = "IsVisible" class="alert alert-info w-100 shadow mt-2" role="alert">
<strong> {{response_msg}} </strong>
</div>
<div class="alert alert-danger " id="filealert"> <strong> File Size should be less than 4 MB </strong></div>
</div>
Angular JS Code
var app = angular.module("myApp", []);
app.directive("fileInput", function($parse){
return{
link: function($scope, element, attrs){
element.on("change", function(event){
var files = event.target.files;
$parse(attrs.fileInput).assign($scope, element[0].files);
$scope.$apply();
});
}
}
});
app.controller("myCtrl", function($scope, $http){
$scope.IsVisible = false;
$scope.uploadFile = function(){
var form_data = new FormData();
angular.forEach($scope.files, function(file){
form_data.append('file', file); //form file
form_data.append('file_Name',$scope.fileName); //form text data
});
$http.post('upload.php', form_data,
{
//'file_Name':$scope.file_name;
transformRequest: angular.identity,
headers: {'Content-Type': undefined,'Process-Data': false}
}).success(function(response){
$scope.IsVisible = $scope.IsVisible = true;
$scope.response_msg=response;
// alert(response);
// $scope.select();
});
}
});

Categories