I have an edit page for an event and one of my fields is a date. In some browsers it seems to act like a plain text box (IE8), however in chrome it displays "dd/mm/yyyy" and if you click on it it has some additional options for setting the date.
My issue though is on the edit page it's not populating the existing date (I imagine because it's not in the correct format?). The MVC controller returns the data in this format "2014-03-08T00:00:00" (just using basic CRUD controller actions).
<form name="form" class="form-horizontal">
<div class="control-group" ng-class="{error: form.EventDate.$invalid}">
<label class="control-label" for="EventDate">Event Date</label>
<div class="controls">
<input type="date" ng-model="item.EventDate" id="EventDate">
</div>
</div>
<div class="form-actions">
<button ng-click="save()" class="btn btn-primary">
{{action}}
</button>
<a href="#/" class="btn">Cancel</a>
</div>
</form>
I've seen quite a few posts on using directives and watches, but that seems complicated. I would have thought there would have been a relatively simple way of formatting the model data so that it displays in the right format and works as expected. I don't mind if Chrome gives a different experience than other browsers - it's just a simple internal user website. I just don't like that it's not prepopulating the date when I edit a record.
set the form inputs. However, Angular forms set inputs via the value property. We have to convert to and from the yyyy-dd-mm date string format if we are working with date objects in our application. Fortunately, we have a couple of workarounds to make it easier to use Date objects and HTML5 date inputs in Angular.
We can work around this limitation by creating a custom Angular Form Control Directive to intercept and map to a Date object or string dynamically. We can enable date objects on our native date inputs by creating an Angular Form Directive that will select an input [type=date] selectors.
But if we only have a date picker and want to get the date once the user selects it, we can use the onChange event to get the value. Let’s create a new application by using the following command. After creating our new application in Angular, we will go to our application directory using this command.
I've created a date parser that converts string to Date objects. You can also provide date formats you're using, as well as your date locale. It returns a Date object, valid or otherwise depending on the input. There's also a directive that implements this parser so you can use it on an input field, for example.
If you want to populate the field with an initial value, then the following will work
//Controller:
$scope.myDate = new Date('2014-03-08T00:00:00');
//HTML:
<input type="date" ng-init="model=(myDate | date:'yyyy-MM-dd')" ng-model="model" />
However, I strongly recommend creating a custom date field directive.
A custom input field directive offers the following benefits:
form.$valid
to false so that you can conditionally submit the form to the server.There are three basic things to consider when implementing a custom date directive:
- A parser that will parse the input text and return the model (in this case, a javascript date).
- A formatter that will format the model and display it in the text field.
- Setting of an optional validation flag which can be used in the UI for custom form validation.
Date Directive:
myApp.directive('dateField', function($filter) {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModelController) {
ngModelController.$parsers.push(function(data) {
//View -> Model
var date = Date.parseExact(data,'yyyy-MM-dd');
// if the date field is not a valid date
// then set a 'date' error flag by calling $setValidity
ngModelController.$setValidity('date', date!=null);
return date == null ? undefined : date;
});
ngModelController.$formatters.push(function(data) {
//Model -> View
return $filter('date')(data, "yyyy-MM-dd");
});
}
}
});
Note: For parsing dates, this directive uses Date.js (an external library).
CSS:
.error {
color:red;
}
.error-border {
border: solid 2px red;
}
HTML:
<form name="myForm">
<input ng-class="{'error-border': myForm.myDate.$error.date}" type="date"
name="myDate" ng-model="myDate" date-field />
<span ng-show="myForm.myDate.$error.date" class="error">
Please enter a valid date!!!
</span>
<br /> Raw Date: {{myDate}}
<br /> Formatted Nicely: {{ myDate | date:'yyyy, MMMM dd'}}
<br /> Is Valid Date? {{ !myForm.myDate.$error.date}}
<br /> Is Form Valid? {{ myForm.$valid }}
</form>
Controller:
myApp.controller('ctrl', function($scope) {
$scope.myDate = new Date('2014-03-08T00:00:00');
});
Demo JS Fiddle with Date.js
Demo JS Fiddle with Moment.js
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With