How to wrap the datetimepicker js into AngularJS directive

前端 未结 7 2171
陌清茗
陌清茗 2020-12-15 01:59

I have spent sometime on researching the existing datetime directives of angularjs.

Both ngularUI and AngularStrap do not provide a datetimepicker as I needed. Of co

相关标签:
7条回答
  • 2020-12-15 02:05

    I really struggled long with Eonasdan datetime picker. Most of the solutions published on the web work ok or not-so ok.

    In the end I merged some of the solutions I have found online. I wrapped it in a working plunker: http://plnkr.co/n8L8UZ

    The directive works using ng-model in moment format, what is more it allows two functions to be passed: onDateChangeFunction and onDateClickFunction which are called respectively.

    Happy using!


    The directive source code:

    angular
        .module('plunker')
        .directive('datetimepicker', [
          '$timeout',
          function($timeout) {
            return {
              require: '?ngModel',
              restrict: 'EA',
              scope: {
                datetimepickerOptions: '@',
                onDateChangeFunction: '&',
                onDateClickFunction: '&'
              },
              link: function($scope, $element, $attrs, controller) {
                $element.on('dp.change', function() {
                  $timeout(function() {
                    var dtp = $element.data('DateTimePicker');
                    controller.$setViewValue(dtp.date());
                    $scope.onDateChangeFunction();
                  });
                });
    
                $element.on('click', function() {
                  $scope.onDateClickFunction();
                });
    
                controller.$render = function() {
                  if (!!controller && !!controller.$viewValue) {
                    var result = controller.$viewValue;
                    $element.data('DateTimePicker').date(result);
                  }
                };
    
                $element.datetimepicker($scope.$eval($attrs.datetimepickerOptions));
              }
            };
          }
        ]);
    
    0 讨论(0)
  • 2020-12-15 02:07

    A possible solution to problem 1:

    You will need to set the view value to the date that is in the model right from the beginning, by doing something like this:

    if (ngModel.$viewValue) {
    
      picker.data("DateTimePicker").setDate(new Date(ngModel.$modelValue));'
    
      picker.on('change', function(e) {
    
        ....
    
      });
    
    }
    
    0 讨论(0)
  • 2020-12-15 02:10

    Can help you with the first point; add $watch to your element inside the link function and set

     value="{{$scope.variableWithTheInitialDate}}" 
    in the text field; that way when loaded, the datetimepicker will be set already.
    For the second point I'd use moment.js but haven't tried your example for telling you how :-P Good luck!

    0 讨论(0)
  • 2020-12-15 02:13

    I ended up putting the input inside of a div and bind model to that. It also includes bootstrapvalidator (Sorry, I didn't have time to make the code perfect, but you should get the idea)

    Sample html code:

    <div datetimepicker="{pickTime: false}" data-ng-model="model.Birthday"><input type="text" name="Birthday" class="form-control" data-date-format="YYYY/MM/DD" data-mask="0000/00/00" data-bv-date="true" data-bv-date-format="YYYY/MM/DD" /></div>
    

    And javascript code:

    app.directive('datetimepicker', function ($timeout) {
    return {
        // Restrict it to be an attribute in this case
        restrict: 'AE',
        // optionally hook-in to ngModel's API 
        require: '?ngModel',
        // responsible for registering DOM listeners as well as updating the DOM
        link: function ($scope, element, $attrs, ngModel) {
            var $element;
            $timeout(function () {
    
                $element = $(element).find("input").datetimepicker($scope.$eval($attrs.datetimepicker));
    
                var DateTimePicker = $element.data("DateTimePicker");
                DateTimePicker.setValueAngular = function (newValue) {
                    this.angularSetValue = true; // a lock object to prevent calling change trigger of input to fix the re-cursive call of changing values
                    this.setDate(newValue);
                    this.angularSetValue = false;
                }
    
                if (!ngModel) { return; }//below this we interact with ngModel's controller
    
                $scope.$watch($attrs['ngModel'], function (newValue) {
                    if (newValue)
                        if (newValue != "Invalid date")
                        {
                            DateTimePicker.setValueAngular(newValue);
                        }
                });
    
                ngModel.$formatters.push(function (value) {
                    // formatting the value to be shown to the user
                    var format = DateTimePicker.format;
                    var date = moment(value);
                    if (date.isValid()) {
                        return date.format(format);
                    }
                    return '';
                });
    
                ngModel.$parsers.push(function toModel(input) {
                    // format user input to be used in code (converting to unix epoch or ...)
                    var modifiedInput = moment(input).format();
                    return modifiedInput;
                });
    
                //update ngModel when UI changes
                $element.on('dp.change', function (e) {
                    if (DateTimePicker.angularSetValue === true)
                        return;
    
                    var newValue = $element[0].value;
                    if (newValue !== ngModel.$viewValue)
                        $scope.$apply(function () {
                            ngModel.$setViewValue(newValue);
                        });
                    //bootstrapvalidator support
                    if ($element.attr('data-bv-field') !== undefined) // if the field had validation
                        $element.closest("form").bootstrapValidator('revalidateField', $element);
    
                });
            });
        }
    };
    }); // directive end
    
    0 讨论(0)
  • 2020-12-15 02:15

    I am also using DateTimePicker by Angular Directive and it is working fine here. I tried it in this way:

    element.datetimepicker({
                            timepicker:false,
                            format:'Y-m-d', 
                            formatDate:'Y-m-d',
                            closeOnDateSelect: true,
                            onChangeDateTime: function(dp, $input){
                                var val = $input['context']['value'];  
                                ctrl.$setViewValue(val); 
                                ctrl.$render();  
                                scope.$apply(); 
                            } 
        //                  minDate:'-1970/01/02', // yesterday is minimum date
                            //maxDate:'+1970/01/02' // and tommorow is maximum date calendar
                        });
    
    0 讨论(0)
  • 2020-12-15 02:16

    To complete cdmckay's solution so the datetime picker widget is correctly initialized with the ng-model's value, I've added a listener on dp.show event. So, my solution is :

    'use strict';
    
    angular.module('frontStreetApp.directives', [])
      .directive('psDatetimePicker', function (moment) {
          var format = 'MM/DD/YYYY hh:mm A';
    
          return {
              restrict: 'A',
              require: 'ngModel',
              link: function (scope, element, attributes, ctrl) {
                  element.datetimepicker({
                      format: format
                  });
                  var picker = element.data("DateTimePicker");
    
                  ctrl.$formatters.push(function (value) {
                      var date = moment(value);
                      if (date.isValid()) {
                          return date.format(format);
                      }
                      return '';
                  });
    
                  /**
                  * Update datetime picker's value from ng-model when opening the datetime picker's dropdown
                  */
                  element.on('dp.show', function() {
                      picker.setDate(ctrl.$viewValue);
                  });
    
                  /**
                  * Update ng-model when  datetime picker's value changes
                  */
                  element.on('change', function (event) {
                      scope.$apply(function () {
                          var date = picker.getDate();
                          ctrl.$setViewValue(date);
                      });
                  });
              }
          };
      });
    
    0 讨论(0)
提交回复
热议问题