2

I am building a directive that adds some logic to the input['date'] element. This is what I have right now:

app.directive('calendarInput', function() {
    'use strict';
    return {
        template : '<input type="date"' +
                            'ng-model="calendarInput"' +
                            'min="{{min}}"' +
                            'max="{{max}}" />'
        replace: true,
        scope: {
            startdate : '@',
            enddate : '@',
            calendarInput: '='
        },
        restrict: 'A',
        link: function (scope, element, attrs) {
            scope.$watch('startdate', function (val) {
                if (val) {
                    var date = new Date(val);
                    scope.min = date.toIsoString().split('T')[0];
                }
            });
            scope.$watch('enddate', function (val) {
                if (val) {
                    var date = new Date(val);
                    scope.max = date.toIsoString().split('T')[0];
                }
            });
        }
    };
});

The idea is to reuse this directive. Sometimes there will be a startdate only, sometimes a enddate only. Like so:

<div calendar-input="item.birthday" enddate="'1990-01-01'"></div>

Unfortunately this always results in an invalid form with the class ng-invalid-min. It's because I don't supply the startdate parameter.

How can I make min or max values optional?

Edit: I am using Angular 1.3.9

dubaniewicz
  • 47
  • 1
  • 4
Sven
  • 6,288
  • 24
  • 74
  • 116

2 Answers2

1

Figured out a way to compile max and min attributes on demand.

app.directive('calendarInput', function($compile) {
    'use strict';
    return {
        template : '<input type="date" class="datepicker" ng-model="omdCalendarInput" />',
        replace: true,
        scope: {
            startdate : '@',
            enddate : '@',
            calendarInput: '='
        },
        restrict: 'CA',
        link: function (scope, element, attrs) {

            var dateInput = element.find('input') // <----

            scope.$watch('startdate', function (val) {
                if (val) {
                    var date = new Date(val);
                    scope.min = date.toIsoString().split('T')[0];
                    if (!dateInput.attr('min')) { // <----
                        dateInput.attr('min', '{{min}}'); // <----
                        $compile(dateInput)(scope); // <----
                    }
                }
            });
            scope.$watch('enddate', function (val) {
                if (val) {
                    var date = new Date(val);
                    scope.max = date.toIsoString().split('T')[0];
                    if (!dateInput.attr('max')) { // <----
                        dateInput.attr('max', '{{max}}'); // <----
                        $compile(dateInput)(scope); // <----
                    }
                }
            });
        }
    };
});

Relevant Link


EDIT: Improved the code above. Also I'm marking this as the correct answer, since nobody else has a solution.

Community
  • 1
  • 1
Sven
  • 6,288
  • 24
  • 74
  • 116
0

This is great, just what I needed. Thank you.

Nit-pick - might want to change:

scope.min = date.toIsoString().split('T')[0];

to

scope.min = $format('date')(date, 'yyyy-MM-dd');

to make it more angularish.

Community
  • 1
  • 1
dubaniewicz
  • 47
  • 1
  • 4