How to wrap datetimepicker js in AngularJS directive

I spent some time researching the existing datetime angular symbol directives.

Both ngularUI and AngularStrap do not provide a datetimepicker as needed. Of course, I know how to use datepicker and timepicker to archive the target.

I searched for a relevant topic from the Internet and stackoverflow. Found interesting and useful information.

http://dalelotts.imtqy.com/angular-bootstrap-datetimepicker/ , there is a datetimepicker, but I do not like the use of this directive.

connecting datetimepicker to angularjs , this topic is very useful, I tried to wrap my datetimepicker directive by following these steps.

My work is based on https://github.com/Eonasdan/bootstrap-datetimepicker , based on datetimepicker based on bootstrap 3, the user interface is very nice.

app.directive('datetimepicker', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attrs, ngModelCtrl) {
            console.log('call datetimepicker link...');
            var picker = element.datetimepicker({
                dateFormat: 'dd/MM/yyyy hh:mm:ss'
            });

            //ngModelCtrl.$setViewValue(picker.getDate());

            //model->view
            ngModelCtrl.$render(function() {
                console.log('ngModelCtrl.$viewValue@'+ngModelCtrl.$viewValue);
                picker.setDate(ngModelCtrl.$viewValue || '');
            });

            //view->model
            picker.on('dp.change', function(e) {
                console.log('dp.change'+e.date);              
                scope.$apply(function(){
                    ngModelCtrl.$setViewValue(e.date);
                });
            });
        }
    };
});

And use it in my view.

<div class="col-md-6">
  <div class="input-group date" id="endTime" data-datetimepicker  ng-model="stat.endTime" data-date-format="MM/DD/YYYY hh:mm A/PM" >
    <input class="form-control" type="text" placeholder="End"/>
    <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span>
    </span>
  </div>
</div>

There are some problems that I have found.

  • If the date is set using json before rendering in the view, the start date is not displayed, I do not see any ngModel rendering method execution log.
  • When I selected the date, it got the date and time based on json data, not the long format. And in another related snippet in the view, row-based date cannot be parsed using the angular date filter.
  • When used in a modal dialog box, this value is not cleared the next time the modal window appears.

Thanks in advance.

+4
7

. , , :

'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 '';
                });

                element.on('change', function (event) {
                    scope.$apply(function() {
                        var date = picker.getDate();
                        ctrl.$setViewValue(date.valueOf());
                    });
                });
            }
        };
    });

HTML:

<!-- The dueDate field is a UNIX offset of the date -->
<input type="text"
       ng-model="dueDate"
       ps-datetime-picker
       class="form-control">

gists .

+4

; $watch

 value="{{$scope.variableWithTheInitialDate}}" 
; , , datetimepicker .
moment.js, , , : -P !
0

1:

, , , - :

if (ngModel.$viewValue) {

  picker.data("DateTimePicker").setDate(new Date(ngModel.$modelValue));'

  picker.on('change', function(e) {

    ....

  });

}
0

cdmckay, ng-model, dp.show. , :

'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 value from ng-model when opening the datetime picker dropdown
              */
              element.on('dp.show', function() {
                  picker.setDate(ctrl.$viewValue);
              });

              /**
              * Update ng-model when  datetime picker value changes
              */
              element.on('change', function (event) {
                  scope.$apply(function () {
                      var date = picker.getDate();
                      ctrl.$setViewValue(date);
                  });
              });
          }
      };
  });
0

, div bind. bootstrapvalidator (, , , )

html-:

<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>

javascript:

app.directive('datetimepicker', function ($timeout) {
return {
    // Restrict it to be an attribute in this case
    restrict: 'AE',
    // optionally hook-in to ngModel 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 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

DateTimePicker Angular, . :

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

Eonasdan datetime picker. , , - .

, . : http://plnkr.co/n8L8UZ

ng-model moment, , : onDateChangeFunction onDateClickFunction, .

!


:

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

Source: https://habr.com/ru/post/1534004/


All Articles