Search code examples
angularjsangular-ui-bootstrapangular-ui

Angular UI datepicker popup open without ng-click


According to official Angular UI documentation for datepicker users in popup style I need to create additional button with ng-click event on it to change $scope property which was binded to is-open attribute like so:

  <p class="input-group">
     <input type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="dt" is-open="popup1.opened" min-date="minDate" max-date="maxDate" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close" alt-input-formats="altInputFormats" />
     <span class="input-group-btn">
        <button type="button" class="btn btn-default" ng-click="open1()"><i class="glyphicon glyphicon-calendar"></i></button>
     </span>
  </p>

In my application it is possible to have more than 10 such datepickers per view so I need to implement property for is-open attribute per each.

Is there any way to open datepicker popup without is-open attribute?


Solution

  • If you have +10 datepickers and repeat the same markup over and over, and need to create $scope functions without any real purpose - then it is almost screaming for a directive to do the trivial tasks! The markup you are repeating can be placed in a template :

    <script type="text/ng-template" id="dateAutomater.html">
      <input type="text" class="form-control"/>
      <span class="input-group-btn">
        <button type="button" class="btn btn-default">
          <i class="glyphicon glyphicon-calendar"></i>
        </button>
      </span>     
    </script>  
    

    The directive (the very basics) could look like this :

    .directive('dateAutomater', ['$compile',  function($compile) {
      return {       
        transclude: true,        
        templateUrl: 'dateAutomater.html',
        restrict: 'AE',                   
        link: function ($scope, element, attrs) {
          $scope.dateInfo = $scope.dateInfo || {};
          var dateInfo = $scope.dateInfo,
              input = element.find('input'),    
              button = element.find('button'),    
              name = input.name || 'date'+Object.keys($scope.dateInfo).length,
              info = {
                open: false,
                click: function() {
                  this.open = true
                }
              }   
    
          dateInfo[name] = info;
          input.attr('ng-model', attrs.dateAutomater);
          input.attr('uib-datepicker-popup', 'dd-MMMM-yyyy');
          input.attr('is-open', 'dateInfo[\"'+name+'\"].open')
          button.attr('ng-click', 'dateInfo[\"'+name+'\"].click()');
    
          $compile(element.contents())($scope);
        }   
      } 
    }])
    

    It simply takes the model as argument, injects the markup from the template and bind the important variable is-open and ng-click function to a self maintained object, $scope.dateInfo. Usage

    <p class="input-group" date-automater="dt"></p>
    <p class="input-group" date-automater="date"></p>        
    <p class="input-group" date-automater="yesterDay"></p> 
    ...
    

    demo -> http://plnkr.co/edit/H6hgYdF420R4IKdjCBGM?p=preview

    Now expand the directive / template to set other default properties you want on the datepicker, like min-date and so on.