Angular-Kendo Date Format Behavior - angularjs

Hello All,
I am running into some problems when using the Kendo-UI date picker in my angular application. Any help would be greatly appreciated.
Thanks in Advance, Drew
Issue
When using the angular-kendo directive for the date picker along with a date format a date object put into the model. The desired behavior is to store a string in the model as formatted by the options.
Javascript Versions
Angular-Kendo 0.5.2 2013-07-26
AngularJS v1.0.5
jQuery jQuery v1.9.1
Snippet from Template
<input type="text" name="publicationDate" ng-model="preview.publicationDate" kendo-date-picker="dateOptions" k-options="dateOptions" />
Date Options
$scope.dateOptions = {
format: "yyyy-MM-dd"
};
Output
Date object stored in model: Tue Sep 17 2013 00:00:00 GMT-0400 (EDT)
Desired string to be stored in model: 2013-09-17
Questions
Is there any remedy for this issue?
Am I using the directive correctly?

In Kendo UI 2014 Q2 (2014.2.625), this is fixed by using k-ng-model instead of ng-model.

I think what is going on is that when you are binding through ng-model, kendo is returning the value of
.value()
In your controller, I believe you can do this:
$scope.$watch('preview.publicationDate'), function (val) {
if (val) {
$scope.preview.publicatonDate = kendo.toString(val, "yyyy-MM-dd");
}
});

This code helps to change the kendo-date-time-picker to the desired format
<input kendo-date-time-picker
k-options="monthSelectorOptions"
k-format="'dd/MM/yyyy hh:mm tt'" />

Possible Solution
I was able to do a work around by creating a custom directive.
The sample provided by another stack overflow post here demonstrates how to create a custom directive.
I still have some additional testing to do but it seems to be working. I am not sure if this is the most efficent way to get around the problem though.
Snippet from Template
<input type="text" parsedate="yyyy-MM-dd" name="publicationDate" ng-model="preview.publicationDate" kendo-date-picker="" k-options="dateOptions"/>
Custom Directive
module.directive("parsedate", function () {
return {
require: "ngModel", link: function (scope, element, attr, ngModel) {
function parsedate(text, format) {
return kendo.toString(text, attr.parsedate);
}
ngModel.$parsers.push(parsedate);
}
};
});

Related

AngularJS input date french

I wanted to use an input[date] inside a form to enable users to use the modern browsers' support, without using a javascript datepicker.
For the ones who're using not supporting browsers, I'v set ui-mask. Both work together.
I use the french format (dd/mm/YYYY).
<input type="date" ng-model="myDate" ui-mask="99/99/9999">
$scope.myDate = new Date("2016-02-12"); // works
$scope.myDate = "12/02/2016"; // Doesn't...
In an empty form, no problem, Angular accept it.
But with a filled form, Angular expects a date format I don't want : YYYY-mm-dd (javascript date object).
I can't understand why Angular only provides support that format, and not others like french format. Because I want the input[date] to show the french format, not the standard one !
Many modern browsers provides interesting support for dates, I can't understand why Angular waste that.
Or maybe I missed something ?
To achieve your goal need to use momentJs and ngModel $parsers and $formatters. Below some code and JSFiddle example:
In your controller you prepare some string value in french date format:
$scope.myDate= '12/02/2016';
In view you set this value to ngModel attribute of input[type=date] element:
<input class="form-control" type="date" ng-model="myDate">
You need to create new directive, it can be assigned to input element:
.directive('input', function(dateFilter) {
return {
restrict: 'E',
require: '?ngModel',
link: function(scope, element, attrs, ngModel) {
if (
'undefined' !== typeof attrs.type && 'date' === attrs.type && ngModel
) {
ngModel.$formatters.push(function(modelValue) {
return moment(modelValue, "DD/MM/YYYY").toDate();
});
ngModel.$parsers.push(function(viewValue) {
return moment(viewValue).format("DD/MM/YYYY");
});
}
}
}
})
New function in $formatters array modifies your myDate to javascript date object (with moment parser it's pretty simple). New function in $parsers array modifies value of input element back to french formatted date string.
This solution provides two way binding between your myDate and input[type=date] element. :)
Look at JSFiddle exaple

Angular Pikaday multiple date format

I am using Pikaday date picker plugin in my angular JS app.
Is it possible to have different format for view and different format while submitting?
For ex: 01 Jan 2014 (Display)
01/01/2014 (while submitting the form)
I know i can apply a filter while posting the content. However, since the date picker is been used in many places i have to do it at all the places separately. It will be great if the plugin updates my ng-model with a certain format but displays it differently.
You can get this by using angularjs directive (formatters and parsers).
For example using moment.js:
app.directive('fdate', function () {
return {
require: 'ngModel',
link: function(elem, $scope, attrs, ngModel){
ngModel.$formatters.push(function(val)
{
return moment(val).format("DD/MM/YYYY");
});
ngModel.$parsers.push(function(val){
return moment(val, "DD/MM/YYYY").valueOf();
});
}
}
});
and in your html:
<input type="text" ng-model="obj.yourdate" fdate>
i found this fiddle as an example:
http://jsfiddle.net/arunpjohny/wNBAn/

Using bootstrap-datepicker with angular xeditable

I have a table and I would like to add in-line editing to that table. I started with ng-grid, however, I decided that while it worked well, I was spending too much time trying to fix the styling so that it would match the overall theme of my website. I started fresh and am now using a plain old html table with angularjs behind the scenes for its awesome two-way-data-binding property.
Everything has been going smoothly except for the fact that I am stuck on trying to get inline editing to work with bootstrap-datepicker: http://www.eyecon.ro/bootstrap-datepicker/?utm_source=twitterfeed&utm_medium=twitter. The reason I am using this datepicker over the ui-bootstrap datepicker that xeditable says you should use is because it does not look or feel right in my website. Here is what the ui-bootstrap datepicker looks like http://jsfiddle.net/NfPcH/23/. I like the simple and plain look of the bootstrap datepicker.
Here is a plunker of a table with xeditable and date fields to try and edit PLUNKER
Using bootstrap-datepicker as an input field works fine, a custom directive is used to properly update the model:
editablegrid.directive('datepicker', function() {
return {
restrict : 'A',
require : 'ngModel',
link : function(scope, element, attrs, ngModelCtrl) {
$(function() {
var dp = $(element).datepicker({
format : 'MM dd, yyyy'
});
dp.on('changeDate', function(e) {
ngModelCtrl.$setViewValue(e.format('MM dd, yyyy'));
scope.$apply();
});
});
}
}
I changed the xeditable source code to use bootstrap-datepicker (see lines 78-84 of xeditable.js)
/*
The New directive I've made for xeditable to use with the bootstrap-datepicker
*/
angular.module('xeditable').directive('editableBsdateNew', ['editableDirectiveFactory',
function(editableDirectiveFactory) {
return editableDirectiveFactory({
directiveName: 'editableBsdateNew',
inputTpl: '<input type="text" class="form-control form-control-inline input-sm" datepicker>'
});
}]);
, however the problem lies somewhere with xeditable and how it updates the model of the selected row.
xeditable works perfectly for editing text and dropdowns in-line, trying to integrate with bootstrap-datepicker is proving to be difficult.
If there is some other way to use in-line editing with bootstrap-datepicker, I would not be opposed to trying it out. I was thinking that if this didn't work, maybe something with ng-show and ng-hide might do the trick.
1 > Make sure you install two libraries
- angular-xeditable
- angular-bootstrap-datepicker
2> Create new directive
/* The New directive I've made for xeditable to use with the
bootstrap-datepicker
*/
angular.module('xeditable').directive('editableBootstrapDatepicker', ['editableDirectiveFactory', function(editableDirectiveFactory) {
return editableDirectiveFactory({
directiveName: 'editableBsdateNew',
inputTpl: '<span ng-datepicker ng-options="datepickerOptions"></span>'
}); } ]);
3> In HTML put something like:
<span editable-bootstrap-datepicker="yourDateModel" onbeforesave="validateBeforeSaveDate($data)">Date ...</span>
Try this:
dp.on('changeDate', function(e) {
ngModelCtrl.$setViewValue(e.format('MM dd, yyyy'));
scope.$apply();
scope.row.dueDate = e.format('MM dd, yyyy'); //<--- new line
});

Angular doesn't validating date type

I'm trying to use input[date] in my form, but angularjs doesn't validate any date:
<form name="myForm">
{{birthday}} <br/>
<input type="date" ng-model="birthday" id="birthday" name="birthday"></input>
</form>
If I try to put "alex" inside the input, it accepts!
JSFiddle: http://jsfiddle.net/3GKeM/2/ (please try with firefox)
You're trying to use a new feature in AngularJS 1.3.x from AngularJS 1.0 which doesn't support type="date".
If you want that support on FireFox. You'll have to use AngularJS. 1.3
The documentation you're referring to is for 1.3
https://docs.angularjs.org/api/ng/input/input%5Bdate%5D
This behaves as expected in Firefox. CanIUse.com reports that this HTML5 feature is not yet supported in Firefox 32 or earlier.
So you'll need to implement a javascript solution if you want all browsers to behave similarly. I'd suggest jQuery UI Datepicker. It's used by a lot of people, has an alright look to it (which you can customize actually) and there are lots of examples on how to use it.
Other options:
Pickdate
Bootstrap Datepicker
And the Angular UI Bootstrap option
Update
You stated that you already have your own datepicker (in comments below), and you are just looking for validation: you may want to consider looking at HTML5 Patterns - Date. They have a variety of Regex solutions for validation. They have several different date formats already in place for you.
And then you can use Angular ng-patter to pass in the regex:
example:
<input type="text" ng-pattern="[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])"></input>
//accepts: YYYY-MM-DD
I would either use ng-validate and a regex to check the format of the input value or because i do believe ng-validate has been deprecated depending on what version you're using, I would use ng-change on the input where you pass the model for the form to a function where you then check the format of the value and set the model to be invalid or valid. Here's a working example I've pulled from my app where i check to see if it is in fact a phone number and that it begins with 1.
checkNumber: function(number,form) {
var num = parseInt(number.replace(/[^0-9\.]+/g, '')),
l = num.toString().length,
first = num.toString()[0];
console.log(num);
if(number && first != '1' || number && l < 11) {
form.$setValidity('phoneNumber',false);
form.phoneNumber.$setValidity('format',false);
} else {
form.$setValidity('phoneNumber',true);
form.phoneNumber.$setValidity('format',true);
}
}
There are browser inconsistencies as to what constitutes a valid date. A valid date string in firefox or ie, is invalid in chrome and vice-versa. I solved a similar issue by creating a custom validation directive that works quite nicely. you can find it here:
http://jsfiddle.net/fortesl/2uv6xmjL/6/
Also shown below:
app.directive('dateFieldValidator', [function () {
var validateDate = function (date, format) {
if (!date.length) {
return true;
}
return moment(date, format.toUpperCase(), true).isValid();
};
return {
restrict: 'A',
require: 'ngModel',
scope: {
dateFormat: '#'
},
link: function (scope, elem, attrs, ngModelCtrl) {
//For DOM -> model validation
ngModelCtrl.$parsers.unshift(function (value) {
var valid = validateDate(value, scope.dateFormat);
ngModelCtrl.$setValidity('validDate', valid);
return valid ? value : undefined;
});
//For Model Update --> DOM
ngModelCtrl.$formatters.unshift(function (value) {
var valid = validateDate(value, scope.dateFormat);
ngModelCtrl.$setValidity('validDate', valid);
return value;
});
}
};
}]);

AngularJS datepicker ui-date bad updates

The two-way data-binding appears to be causing bad updates to the field. Clicking on the field raises the datepicker fine, but if you attempt to edit the field by directly typing in a date, it doesn't quite work.
Here's the fiddle demonstrating the issue: http://jsfiddle.net/vSNJF/
<input type="text" ng-model="name" ui-date-format='m/d/yy' ui-date>
Compare the keyboard-editing under Angular to the standard jquery UI date picker behavior here: http://jqueryui.com/datepicker/
How can I make ui-date delay updating the model until after the interactive calendar is dismissed?
You've got quite a big directive there, I am not sure if anyone is going to go through the whole code to find what is causing the problem. To help I will leave a simpler datepicker directive that behaves exactly like Jquery UI's but without all the features you have implemented in yours, maybe if your start from this point and go adding features it would be easier to debug the problem.
The directive is:
directive('datepicker', function() {
return {
restrict: 'A',
require : 'ngModel',
link : function (scope, element, attrs, ngModelCtrl) {
$(function(){
element.datepicker({
dateFormat:'dd/mm/yy',
onSelect:function (date) {
ngModelCtrl.$setViewValue(date);
scope.$apply();
}
});
});
}
}
});
Here is a Plunker and a blog post about it.

Resources