Is there a way in angular JS to get Timestamp from a date obtained by a form?
<label for="start">From:</label>
<input type="date" ng-model="startDate" />
What will I have to write in the directive to transform this data? I didn't find anything about this particular issue,
Regards
Since you are using input type as date, the string in model should be compatible with Date object in javascript. So you can do
var timestamp = new Date($scope.startDate).getTime()
Use a directive to change the value from view to model.
http://jsfiddle.net/bateast/Q6py9/1/
angular.module('app', [])
.directive('stringToTimestamp', function() {
return {
require: 'ngModel',
link: function(scope, ele, attr, ngModel) {
// view to model
ngModel.$parsers.push(function(value) {
return Date.parse(value);
});
}
}
});
To use in a controller you can do something like this:
myApp.controller('TimestampCtrl', ['$scope', function($scope) {
$scope.toTimestamp = function(date) {
var dateSplitted = date.split('-'); // date must be in DD-MM-YYYY format
var formattedDate = dateSplitted[1]+'/'+dateSplitted[0]+'/'+dateSplitted[2];
return new Date(formattedDate).getTime();
};
}]);
And can be used like this:
<div ng-controller="TimestampCtrl">
The timestamp of <input ng-model="date"> is {{ toTimestamp(date) }}
</div>
Related
I had datepicker using jquery. It works when the page is loaded because i set the default date in my controller. Picking a date is ok but the problem is when you get the value using angular js its not updated, always the default value. Anyone how to update the value when date is selected and set by jquery. Really appreciate your help and thanks in advance.
html
<input type="text" id="date1" name="date1" ng-model="data.date1">
<input type="text" id="date2" name="date2" ng-model="data.date2">
<button type="button" ng-click="get()">Test Value</button>
jquery
$('#date1').datepicker({
language: 'en',
autoClose:true,
dateFormat: 'd MM yyyy',
onSelect: function (fd, date, picker) {
}});
$('#date2').datepicker({
language: 'en',
autoClose:true,
dateFormat: 'd MM yyyy',
onSelect: function (fd, date, picker) {
}});
angular js
var app = angular.module('app', []);
app.controller('MainController', function($scope, $http){
$scope.data = {};
// default date
$scope.data.date1 = new Date();
$scope.data.date2 = moment(new Date()).add(1, 'days');
$scope.get = function(){
console.log($scope.data.date1);
console.log($scope.data.date2);
}});
If you are about to use datepicker more than one time, I suggest to create directive and just use it.
Directive
app.directive('datepicker', function() {
return {
restrict: 'A',
require : 'ngModel',
link : function (scope, element, attrs, ngModelCtrl) {
$(function(){
element.datepicker({
dateFormat:'dd/mm/yy',
onSelect:function (date) {
scope.$apply(function () {
ngModelCtrl.$setViewValue(date);
});
}
});
});
}
}
});
HTML
<input type="text" ng-model="date1" datepicker />
<input type="text" ng-model="date2" datepicker />
For more detail, just check this Plunker
I have two custom datepicker directives. One is called startDatePicker directive and the second is endDatePicker. I'm passing model from one to another which is fine, however when I pass date as string it does not display the date. I know it shouldn't because datepicker expects date object and it cannot convert it to date object automatically. Because my backend server returns dates as strings I need to convert to date objects. For that I use model.$formatter in my directive to convert string to date object and then send it to the view so the date can be selected and displayed. The date is getting selected, but it's not getting displayed..
To simulate the issue I have defined two variables in my controller. These two will be used for datepicker models as well. The first variable gets selected and displayed in the datepicker, but second only gets selected, but not displayed. What I'm doing wrong?
$scope.startDate = moment.utc("2016/12/25 00:00:00")._d;
$scope.endDate = "2016/12/25 00:00:00";
I have setup plunker to show the issue http://plnkr.co/edit/trEkwuO06VMJ1HdCkl5w?p=preview
Complete directive below
angular.module('ui.bootstrap.demo').directive('endDatepicker', function() {
return {
restrict: 'A',
scope: {
ngModel: "=",
minStartDate: "=",
},
require: 'ngModel',
replace: true,
templateUrl: 'datepicker-template.html',
link: function(scope, element, attrs, ngModel) {
ngModel.$formatters.push(function getJsonDate(date) {
if (!date) return null;
console.log("Unformatted date " + date)
var newDate = moment.utc(date)._d;
console.log("Formatter fired " + newDate)
return newDate
});
scope.popupOpen = false;
scope.openPopup = function($event) {
$event.preventDefault();
$event.stopPropagation();
scope.popupOpen = true;
};
console.log(scope.endDate);
scope.$watch('minStartDate', function(newValue,oldValue){
if (newValue) {
console.log(newValue)
scope.dateOptions.minDate = newValue;
}
})
scope.dateOptions = {
startingDay: 1,
minDate: moment.utc()._d
}
scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
scope.opened = true;
};
}
};
});
This can be a confusing issue.
Right there will be two ngModel controllers associated with the endDatepicker directive.
One for ng-model here:
<div end-datepicker ng-model="endDate" min-start-date="startDate"></div>
And one for ng-model in the template:
<input type="text" class="form-control" ... ng-model="ngModel" ...
Both controllers will work with the same model, but you need to add the formatter to the correct one.
When you require the controller in your directive you will get the ngModel controller for the first one, but you need the controller for the ngModel on the input where the formatted value is to be shown.
Instead of requiring the controller the following should work:
link: function(scope, element, attrs, ngModel) {
var inputModelController = element.find('input').controller('ngModel');
inputModelController.$formatters.push(function getJsonDate(date) {
// Code
});
I'm trying to create an input mask for a EU money field using http://jquerypriceformat.com/
So far in my directive, the input shows correctly to the user with the mask applied, but I believe there's something wrong, because the POST values are being sent with weird formatting, totally different than what we see in the input field.
I include the priceformat.js
<script src="js/jquery.price_format.1.8.min.js"></script>
<input type="text" currency-input ng-model...>
And on angular:
app.directive('currencyInput', function() {
return {
require: '?ngModel',
link: function($scope, element, attrs, controller) {
element.priceFormat({
prefix: '',
centsSeparator: ',',
thousandsSeparator: '.'
});
}
};
});
My input shows the value with the mask correctly, but on POST data (called by angular) it's a different value, what am I missing?
input > 2.200,80 | post > 22,0080
Thanks
From your example I don't see that link returns something.
I would write directive something like:
.directive('format', ['$filter', function ($filter) {
return {
require: '?ngModel',
link: function (scope, elem, attrs, ctrl) {
if (!ctrl) return;
ctrl.$formatters.unshift(function (a) {
return $filter(attrs.format)(ctrl.$modelValue)
});
ctrl.$parsers.unshift(function (viewValue) {
elem.priceFormat({
prefix: '',
centsSeparator: ',',
thousandsSeparator: '.'
});
return elem[0].value;
});
}
};
}]);
Demo 1 Fiddle
If you want on start fire the filter, use $formatters:
Now link is:
link: function (scope, elem, attrs, ctrl) {
if (!ctrl) return;
var format = {
prefix: '',
centsSeparator: ',',
thousandsSeparator: ''
};
ctrl.$parsers.unshift(function (value) {
elem.priceFormat(format);
return elem[0].value;
});
ctrl.$formatters.unshift(function (value) {
elem[0].value = ctrl.$modelValue * 100 ;
elem.priceFormat(format);
return elem[0].value;
})
}
Demo 2 Fiddle
Push a $parser to the controller, and only update the value when it doesn't match the input using $setViewValue() and $render().
app.directive('currencyInput', function() {
return {
require: '?ngModel',
link: function($scope, element, attrs, controller) {
return ctrl.$parsers.push(function(inputValue) {
...
if (result != inputValue) {
controller.$setViewValue(res);
controller.$render();
}
});
}
};
});
Here's a fiddle with the logic I used for my currency input directive: Fiddle
Late to the party, but I believe this deserves another answer! I've been using the ng-currency module. It's absolutely fantastic.
I like Dubilla's approach cause of its simplicity and elegance. I decided to add (with due credits) some features on top of it to make it quite close to real world use case.
I've using it on a github project to create some useful finance directives github.
Notable extra features:
It does some rigorous checking of the inputs to give a valid response.
It has some keyboard shortcuts to make entering large numbers quicker.
I show how to integrate it with bootstrap and ngmodel css updates.
As a bonus I outputed the form's ngmonel as JSON to help people see how the form validation works in real time
It also uses a POJO as the ngmodel:
function Money() {
this.notional = 0;
this.maxValue = 99999999999.9;
this.maxValueString = "99,999,999,999.9";
this.maxPrecision = 10;
}
you can use it with Bootstrap 3 like so:
<h1>Currency Formatting directive</h1>
<div class="row">
<div class="col-md-6">
<form name="myForm">
<div class="form-group" ng-class="{'has-error': myForm.notional.$invalid && myForm.notional.$touched}">
<input type="text" ng-model="myForm.money.notional " money="money" money-input size="30" required
name="notional"
class="form-control"
placeholder="Enter notional amount"/>
<p class="help-block error" ng-show="myForm.notional.$error.required && myForm.notional.$touched">Required</p>
</div>
<button ng-disabled="myForm.$invalid" type="submit">SAVE</button>
</form>
<h2>Tips</h2>
<ol>
<li> Entering 'k' will multiply the amount by one thousand</li>
<li> Entering 'm' will multiply the amount by one million</li>
<li> Entering 'b' will multiply the amount by one billion</li>
</ol>
</div>
</div>
<p>Form debugger</p>
<pre>
form = {{ myForm | json }}
</pre>
Here's a way to handle this without jQuery using only an Angular directive. This example doesn't support decimals. It's easy to modify it to support that though, just change the $filter in the toView() function.
In my opinion this is a better approach to solve the same problem, as you can avoid loading in jQuery and the currency plugin mentioned by the author. Locale support for Euro should be supported by the use the $locale properties, but I've only tested this for use in USD.
(function() {
var app = angular.module('currencyMask', []);
// Controller
app.controller('ctrl', ['$scope', function($scope) {
$scope.amount = 100000;
}]);
// Directive
app.directive('inputCurrency', ['$locale', '$filter', function($locale, $filter) {
// For input validation
var isValid = function(val) {
return angular.isNumber(val) && !isNaN(val);
};
// Helper for creating RegExp's
var toRegExp = function(val) {
var escaped = val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
return new RegExp(escaped, 'g');
};
// Saved to your $scope/model
var toModel = function(val) {
// Locale currency support
var decimal = toRegExp($locale.NUMBER_FORMATS.DECIMAL_SEP);
var group = toRegExp($locale.NUMBER_FORMATS.GROUP_SEP);
var currency = toRegExp($locale.NUMBER_FORMATS.CURRENCY_SYM);
// Strip currency related characters from string
val = val.replace(decimal, '').replace(group, '').replace(currency, '').trim();
return parseInt(val, 10);
};
// Displayed in the input to users
var toView = function(val) {
return $filter('currency')(val, '$', 0);
};
// Link to DOM
var link = function($scope, $element, $attrs, $ngModel) {
$ngModel.$formatters.push(toView);
$ngModel.$parsers.push(toModel);
$ngModel.$validators.currency = isValid;
$element.on('keyup', function() {
$ngModel.$viewValue = toView($ngModel.$modelValue);
$ngModel.$render();
});
};
return {
restrict: 'A',
require: 'ngModel',
link: link
};
}]);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
<div ng-app="currencyMask" ng-controller="ctrl">
<input input-currency ng-model="amount">
<p><strong>Amount:</strong> {{ amount }}</p>
</div>
I'm trying to use angular strap datepicker
When I select the date, it returns string like "2013-10-21T00:00:00.000Z"
But when I set this string to variable he doesn't react...
i tried this ways
$scope.var1="2013-10-14T00:00:00.000Z";
$scope.var1= {date: new Date("2013-10-14T00:00:00.000Z")};
$scope.var1="08/10/2012";
Here is plunker
How to send date to him?
And is there any way to interact with it? Or i must use only var1 assigned as his model?
The string like 2013-10-14T00:00:00.000Z represents by new Date().
To store form, you can do that by create custom directive:
directive
app.directive('datetimez', function() {
return {
restrict: 'A',
require : 'ngModel',
link: function(scope, element, attrs, ngModelCtrl) {
element.datepicker({
dateFormat:'dd/MM/yyyy',
}).on('changeDate', function(e) {
console.log(e.date);
ngModelCtrl.$setViewValue(e.date);
scope.$apply();
});
}
};
});
HTML
<input id="inputDatepicker" class="input-small" type="text" datetimez ng-model="var1" data-date-format="dd/mm/yyyy" >
See demo Plunker
Hopfully this is helpful to someone else... I just spent 20 min looking for this.
HTML:
<input type="date" id="date" ng-model="object.date">
CONTROLLER:
.controller('yourController', function($scope) {
$scope.object = {
date: new Date()
}
});
I have this html:
<form name="form" novalidate data-ng-submit="TradeDaysFormSubmit()">
<div data-ng-repeat="tradeDay in tradeDays">
{{ tradeDay }}
<br />
<div inline-calender class="trade-calender-box" date="tradeDay" data-ng-model="tradeDay"></div>
</div>
</form>
With this controller:
$scope.tradeDays = [];
$scope.tradeDays.push("31-01-2013");
$scope.tradeDays.push("28-02-2013");
$scope.tradeDays.push("10-03-2013");
$scope.tradeDays.push("11-04-2013");
$scope.tradeDays.push("12-05-2013");
$scope.tradeDays.push("13-06-2013");
$scope.tradeDays.push("11-07-2013");
$scope.tradeDays.push("23-08-2013");
$scope.tradeDays.push("14-09-2013");
$scope.tradeDays.push("30-10-2013");
$scope.tradeDays.push("22-11-2013");
$scope.tradeDays.push("23-12-2013");
$scope.tradeDays.push("31-01-2014");
And the directive:
app.directive("inlineCalender", function () {
return {
restrict: 'A',
require: 'ngModel',
scope: {
date:'='
},
link: function (scope, element, attributes, modelController) {
scope.$watch('date', function (newValue) {
if (!_.isString(newValue)) return;
dateparts = scope.date.split('-');
var minDate = new Date(dateparts[2], parseInt(dateparts[1]) - 1, 1);
var maxDate = new Date(dateparts[2], parseInt(dateparts[1]), 0);
element.datepicker({ defaultDate: scope.date, hideIfNoPrevNext: true, minDate: minDate, maxDate: maxDate });
element.bind("change", function (event) {
var currentDate = element.datepicker("getDate");
scope.date = currentDate;
modelController.$setViewValue(currentDate.toString());
modelController.$render();
scope.$apply();
});
});
}
}
});
The view shows all my calenders, so far so good. But, when I change a date, the new value is not passed to the model. As you can see, in the HTML I have {{ tradeDay }}, but this value doesn't change when I select a date on my calender.
Can someone tell me what I am doing wrong here? I've tried the model controller, and isolate scope with two-way binding, but neither did work.
Fiddle When you click a date in the datepicker, the text above is not updated.
There is just a small mistake in your code you should be using dot in a model just change your code to below and it will work
http://jsfiddle.net/Qvu5u/3/
Just use dot model like
$scope.tradeDays.push({date:'31-01-2013'});
https://github.com/angular/angular.js/wiki/Understanding-Scopes
The best practice to deal with the isolated scope is always have a '.' in your ng-models.
You can remove the $watch to prevent $apply to trigger multiple times. (You can see that in your code if you log something before $apply)
The date change can be easily captured by the callback function of the calender, you can change the code to:
link: function (scope, element, attributes, modelController) {
dateparts = scope.date.split('-');
var minDate = new Date(dateparts[2], parseInt(dateparts[1]) - 1, 1);
var maxDate = new Date(dateparts[2], parseInt(dateparts[1]), 0);
element.datepicker({
defaultDate: scope.date,
hideIfNoPrevNext: true,
minDate: minDate,
maxDate: maxDate,
onSelect: function (date) {
modelController.$setViewValue(date);
scope.date = date;
scope.$apply();
}
});
}
Demo on jsFiddle