0

I am building a dynamic form and am using the HTML5 date input for fields of type date. I was struggling to get the date input to display my date, and have come to the conclusion the value has to be a JavaScript date or the date will not display. If I am wrong on that, someone please correct me because it doesn't seem like it should be a requirement. Because my fields are dynamic I can't simply initialize specific fields to a Date, so I created a directive to convert to a JavaScript date.

angular.module( 'convertDate-directive', [] )
.directive('convertDate', function( $parse ) {
    return {
        restrict: "A",
        link: function( scope, element, attrs ) {
            var fieldModel = $parse( attrs.ngModel );
            var fieldValue = fieldModel( scope );
            fieldModel.assign( scope, new Date( fieldValue ) );
        }
    };
});

Here is my date input, which is rendered only if the field is of type date:

<input type="date"
       ng-if="field.type == 'date'"
       dynamic-model="field.name"
       ng-model="field.name"
       name="field.name"
       max="{{field.maxValue | date : 'yyyy-MM-dd'}}"
       min="{{field.minValue | date : 'yyyy-MM-dd'}}"
       ng-required="field.required"
       ng-model-options="{ updateOn: 'blur' }"
       convert-date
       class="form-control">

The problem with this directive is it triggers a $watch that I have on an object in my controller, which determines whether changes have been made and a save is needed.

My watch code:

$scope.$watch( 'application.' + resource.name, function( newValue, oldValue ) {
    if ( newValue !== oldValue ) {
        resource.changed = true;
    }
}, true );

Is there any way to suppress the change event in this scenario? Or, is there a better way to initialize an HTML5 date field? Looking for ideas. Thanks!

5
  • Sorry I don't understand what you want. So you do have already setup a $watch and can determine when there is a change. What do you want to then suppress? Commented Aug 18, 2014 at 23:20
  • The $watch fires any time the value of one of my fields changes. I don't want it to fire when I am simply initializing a date using new Date(). I want the HTML5 date input to display my date. The issue with $watch firing is a side effect of the directive I created and I would like to find a way to prevent that from happening, or I'm open to other suggestions if there is a better way to go about it than the directive I created. Commented Aug 18, 2014 at 23:43
  • I see. Well, the $watch is going to fire everytime the model changes. What is the problem though with the $watch firing? You can check to make sure the newValue != oldValue and typeof oldValue !== 'undefined' to detect a change. When you initialize, oldValue is undefined, so that's what the second if statement is for. I posted it as a solution. Commented Aug 19, 2014 at 0:05
  • Did you see my comment on your answer? Commented Aug 19, 2014 at 0:20
  • I posted the answer after your comment on snowman's post! can you review your comment, and post it under my question if it is still relevant? Commented Aug 19, 2014 at 0:23

2 Answers 2

1

A date input doesn't require the value to be set as a Date object. It requires it to be in ISO format. See this question/answer for more details: pre-populating date input field with Javascript

Sign up to request clarification or add additional context in comments.

2 Comments

Yes, I tried hardcoding a date in my controller in the format of yyyy-MM-dd to see if it would display in the date input and it did not. However, after seeing your answer I decided to try again with version 1.2.9 of Angular and it worked, so it must have been a bug in the beta version of 1.3.0 we are using. I upgraded to a newer beta version and it worked, so must have been fixed at some point. Thanks for confirming a JavaScript Date object is not required.
From Angular 1.2 to 1.3 migration guide: input: types date, time, datetime-local, month, week now always require a Date object as model. That explains why it wasn't working with 1.3.
0

$watch is fired every time there is a change in your scope value, this includes the initialization. However, you can use the fact that the old value is undefined before the initialization takes place:

$scope.$watch('field.name', function(newValue, oldValue)
{
    // Do not save if there is no change
    // OR this is an initialization (oldValue is undefined)
    if (newValue == oldValue || typeof oldValue === 'undefined') return;

    // Run your save() function now
});

1 Comment

oldValue will initially be either a Unix timestamp or an ISO 8601 string, so it won't be undefined. I am replacing the value in the model with a Date object. I could possibly check if typeof oldValue != typeof newValue, but that seems kind of hackish to me. Another option would be to convert oldValue to a Date and compare with newValue, but that would require me to know they are supposed to be dates.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.