2

I want to create a directive that will allow a user to input a date in a wide variety of formats. When the underlying model changes (whether via direct user input, or programmatically), I would like it to display the date in a normalized format.

An example of this "in the wild" are the departure and return date inputs on Google Flights.

Here's my code (which does not work at all).

VIEW

<input type="text" ng-model="params.departDate" 
  date-input display-format="{Weekday} {d} {Month}, {yyyy}">

CONTROLLER

app.controller('MainCtrl', function($scope) {
  $scope.params = {
      departDate: new Date()
  };
  $scope.isDate = function() {
      return $scope.params.departDate instanceof Date;
  }
});

DIRECTIVE

app.directive("dateInput", function() {
    return {
        require: 'ngModel',
        scope: {
            displayFormat: '@'
        },
        link: function (scope, element, attrs, ngModel) {

            ngModel.$parsers.push(function (viewVal) {
                if (viewVal) {
                    // Using sugar.js for date parsing
                    var parsedValue = Date.create(viewVal);
                    if (parsedValue.isValid()) {
                        ngModel.$setValidity("date", true);
                        return parsedValue;
                    }
                }
                ngModel.$setValidity("date", false);
                return viewVal;
            });

            ngModel.$formatters.unshift(function (modelVal) {
                if (modelVal){
                    // Using sugar.js for date formatting
                    var date = Date.create(modelVal);
                    if (date.isValid()) {
                        return date.format(scope.displayFormat || '{Weekday} {d} {Month}, {yyyy}')
                    }
                }
                return modelVal;
            });
        }
    };
})

This doesn't even come close to working as I would expect. What am I doing wrong?

Here's a PLUNKR: http://plnkr.co/edit/583yOD6aRhRD8Y2bA5gU?p=preview

jessegavin
  • 74,067
  • 28
  • 136
  • 164
  • 3
    ng-model and isolate scopes don't mix well: http://stackoverflow.com/questions/11896732/ngmodel-and-component-with-isolated-scope I suggest not creating any scope in your directive, and access the display-format attribute using attrs: `var displayFormat = attrs.displayFormat`. – Mark Rajcok Aug 01 '13 at 15:25
  • 2
    Thank you 1000 times! You just saved me $500 for a new monitor which I was about to smash with a brick out of frustration. – jessegavin Aug 01 '13 at 15:35

2 Answers2

3

As mentioned in a comment, ng-model and isolate scopes don't mix well, see Can I use ng-model with isolated scope?.

I suggest not creating any scope in your directive, and access the display-format attribute using attrs:

var displayFormat = attrs.displayFormat;
Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
1

I also prefer isolated scope with reusable directives, in that case ng-model has to be given proper path to parent scope: ng-model="$parent.params.departDate"

updated plunker: http://plnkr.co/edit/DuR6Om2kyzWD67hYExSh?p=preview

user2656492
  • 41
  • 1
  • 1