Question

I am making a date range angular directive. This uses two ui.bootstrap date pickers for the start and end dates.

I am watching the start and end dates to adjust them if one of the selected dates goes further than 3 months from the other.

The models update correctly, as I can see them update when printed directly to the screen, however the dates within the text fields does not.

My guess is that the text field date is not directly tied to the model and requires a function to be run to update the text field.

The example directive code is given below, and is functional within a plunker.

var app = angular.module('app', ['ui.bootstrap']);
app.directive("dateRange", function() {
  return {
    restrict: "A",
    templateUrl: "date-range.html",
    controller: [
      "$scope",
      "$attrs",
      "$element",
      function($scope, $attrs, $element) {
        // Watch the start/end dates for external changes.
        // If they get too far apart, modify the other date to bring it inline.
        $scope.$watch("dateRange.start", function(startDate) {
          var max = new Date(startDate);
          max.setMonth(startDate.getMonth() + 3);
          if ($scope.dateRange.end.getTime() > max.getTime()) {
            $scope.dateRange.end.setTime(max.getTime());
          }
        });
        $scope.$watch("dateRange.end", function(endDate) {
          var min = new Date(endDate);
          min.setMonth(endDate.getMonth() - 3);
          if ($scope.dateRange.start.getTime() < min.getTime()) {
            $scope.dateRange.start.setTime(min.getTime());
          }
        });
        $scope.dateRange = {
          start: (function() {
            var date = new Date();
            date.setMonth(date.getMonth() - 1);
            return date;
          })(),
          end: new Date(),
        };
      }
    ]
  };
});

app.directive("datePicker", function() {
  return {
    restrict: "A",
    scope: {
      model: "=model",
      label: "@label"
    },
    templateUrl: "date-picker.html",
    controller: [
      "$scope",
      "$attrs",
      "$element",
      function($scope, $attrs, $element) {
        $scope.open = function($event) {
          $event.preventDefault();
          $event.stopPropagation();

          $scope.opened = true;
        };
        $scope.format = "dd-MM-yyyy";
      }
    ]
  };
});
Était-ce utile?

La solution

I've written a Directive that could give you a hint on how to greatly simplify your attempt using AngularJSs builtin-in service $parse and injecting the ngModel Controller.

app.directive('coupledDate', ['$parse',
    function ($parse) {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attrs, ngModelCtrl) {
                if(attrs.difference){
                    scope.$watch(attrs.dateFrom, function (newValue, oldValue, scope) {
                        var future = moment(newValue).add('d', Number(scope.$eval(attrs.difference))).toDate();
                        $parse(attrs.ngModel).assign(scope, future);
                    });
                }
                //Validation Part:
                element.on('blur', function () {
                    scope.$apply(function () {
                        var from = moment(scope.$eval(attrs.dateFrom));
                        var till = moment(scope.$eval(attrs.ngModel));
                        ngModelCtrl.$setValidity('date', from.isBefore(till));
                    });
                });
            }
        };
    }
]);

When applying this directive to a Datepicker Field it will watch a variable on the scope specified with the date-from tag and add the amount of days specified by the difference tag. Further Possibilities include Validation etc. This directive is using moment.js.

As a preview i created a plunker for you http://plnkr.co/edit/RQZCJhQDaD0ZPURTS0Lp?p=preview

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top