The Modular Angularjs dialog box does not recognize the click event from Datepair

advertisements

I'm using bootstrap modal with angularjs along with datepair.

http://jonthornton.github.io/Datepair.js/

I'm working on creating a single page leave request calendar where I can add leave request to the calendar via a modal dialog box. When the box pops up, you pick your date and time you'll be absent from work. I'm experiencing an issue where the datepair doesn't work when nested within the modal dialog template.

The modal dialog works in the following code, but a click doesn't seem to trigger the calendar or time popup like in the demo link provided above. Everything works fine outside of the angularjs / modal template.

var app = angular.module('myModule', ['ui.bootstrap']);

app.controller('ModalDemoCtrl', function ($scope, $uibModal, $log) {

  $scope.animationsEnabled = true;

  $scope.open = function (size) {

    var modalInstance = $uibModal.open({
      animation: $scope.animationsEnabled,
      templateUrl: 'myModalContent.html',
      controller: 'ModalInstanceCtrl',
      size: size,
    });

    modalInstance.result.then(function (selectedItem) {
      $scope.selected = selectedItem;
    }, function () {
      $log.info('Modal dismissed at: ' + new Date());
    });
  };

  $scope.toggleAnimation = function () {
    $scope.animationsEnabled = !$scope.animationsEnabled;
  };

});

//Please note that $modalInstance represents a modal window (instance) dependency.
//It is not the same as the $uibModal service used above.
app.controller('ModalInstanceCtrl', function ($scope, $uibModalInstance, items) {

    $http.get('./requestType.json')
    .success(function (data) {
        $scope.requestTypeList = data;
    });

    // initialize input widgets first
    $('#requestForm .time').timepicker({
        'showDuration': true,
        'timeFormat': 'g:ia'
    });

    $('#requestForm .date').datepicker({
        'format': 'm/d/yyyy',
        'autoclose': true
    });

    // initialize datepair
    var requestForm = document.getElementById('requestForm');
    var datepair = new Datepair(requestForm);

    $scope.ok = function () {
     $uibModalInstance.close($scope.selected.item);
    };

    $scope.cancel = function () {
     $uibModalInstance.dismiss('cancel');
    };
});

html

                <script type="text/ng-template" id="myModalContent.html">
                    <div class="modal-header">
                        <h3 class="modal-title">I'm a modal!</h3>
                    </div>
                    <div class="modal-body">
                                    <form ng-submit="submitForm()" form-autofill-fix name="form">
                                        <p id="requestForm">
                                            <label>Request Type</label>
                                            <select ng-model="formData.requestType" ng-options="rt.name for rt in requestTypeList track by rt.id" required class="form-control">
                                                <option value="">- Select Request Type</option>
                                            </select>
                                            <label>Start Date</label><input type="text" class="form-control date start" ng-model="formData.startDate" required/>
                                            <label>Start Time</label> <input type="text" class="form-control time start" ng-model="formData.startTime" required/>
                                            <label>End Time</label><input type="text" class="form-control time end" ng-model="formData.endTime" required/>
                                            <label>End Date</label><input type="text" class="form-control date end" ng-model="formData.endDate" required/>
                                             <ul>
                                                <li ng-repeat="item in items">
                                                    <a href="#" ng-click="$event.preventDefault(); selected.item = item">{{ item }}</a>
                                                </li>
                                            </ul>
                                        </p>
                                        <input type="submit" value="Add to Agenda" class="btn btn-success"/>
                                    </form>
                    </div>
                    <div class="modal-footer">
                        <button class="btn btn-primary" type="button" ng-click="ok()">OK</button>
                        <button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
                    </div>
                </script>

Now requestTypeList works perfectly to load the select menu, but if I click the date field, nothing pops up. Does anybody have any idea what might be wrong?


I think the problem is that ModalInstanceCtrl is executing before template inserted to the DOM. The first rule of angular: do not use angular do not do DOM Manipulations from controllers, services or anywhere else but from directives.

So instead of doing this

$('#requestForm .time').timepicker({
    'showDuration': true,
    'timeFormat': 'g:ia'
});

from modal's controller make an directive for this:

(function () {
  'use strict';

    angular
      .module('xp-timepicker', [])
      .directive('xpTimepicker', timepicker);

    function timepicker() {
      return {
        restrict: 'A',
        link: function (scope, element, attrs) {
          element.timepicker({
            showDuration: true,
            timeFormat: 'g:ia'
          });
        }
      };
    }
}());

// to use your directive in your app include it's module as dependency for your app module
angular
  .module('app', ['xp-timepicker']);

Then place this directive on input fields you need:

<input type="text" ng-model="time" xp-timepicker>

I made a working plunker for you.