Monday, May 4, 2015

JQuery UI with AngularJS Directive, Datepicker, migration to AngularJS new version

henriquat.re  is an interesting project on AngularJS from the .net developer’s point of view. Their article  on  Combining AngularJS with existing Components gives an elegant approach to combine JQuery UI datepicker fragment and move it to a reusable AngularJS directive.
When I tried the code with the latest AngularJS and JQuery UI releases the code did not work. I researched and found the problem. As stated in AngularJS Migrating from Previous Versions 
“Due to 3f2232b5, $controller will no longer look for controllers on window. The old behavior of looking on window for controllers was originally intended for use in examples, demos, and toy apps. We found that allowing global controller functions encouraged poor practices, so we resolved to disable this behavior by default.
To migrate, register your controllers with modules rather than exposing them as globals:”
I also used the idea given in Stackflow question  Adding directive makes controller undefined in angular js code  answered by James Allardice.
My modified code is given below
HTML index.html
 <link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
  <script src="http://code.jquery.com/jquery-1.10.2.js"></script>
  <script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<!--
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script>
-->
<!-- Embedded Fragment - maindiv -->
<div ng-app="demo" ng-controller="DemoController">
    Date Of Birth:
    <my-datepicker type="text" ng-model="user.dateOfBirth" />
    <br>
    Current user's date of birth:
    <span id="dateOfBirthDisplay">{{user.dateOfBirth}}</span>
</div>
<!-- Fragment End - maindiv -->

<!--<script src="angular.js"></script>-->
<!-- <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>-->
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>

<script src="demo.js"></script>
<link rel="stylesheet" href="demo.css">
 
JavaScript 
demo.js
/* Embedded Fragment - controller */
//function DemoController($scope) {
//   $scope.user = {
//      dateOfBirth: new Date(1970, 0, 1)
//   }
//}
//
var demo = angular.module("demo", []);
//
demo.controller("DemoController",  function($scope) {

   $scope.user = {
      dateOfBirth: new Date(1970, 0, 1)
       
   }
});
/* Fragment End - controller */

/* Embedded Fragment - directive */

demo.directive('myDatepicker', function ($parse) {
   return {
      restrict: "E",
      replace: true,
      transclude: false,
      compile: function (element, attrs) {
         var modelAccessor = $parse(attrs.ngModel);

         var html = "<input type='text' id='" + attrs.id + "' >" +
            "</input>";

         var newElem = $(html);
         element.replaceWith(newElem);

         return function (scope, element, attrs, controller) {

            var processChange = function () {
               var date = new Date(element.datepicker("getDate"));

               scope.$apply(function (scope) {
                  // Change bound variable
                  modelAccessor.assign(scope, date);
               });
            };

            element.datepicker({
               inline: true,
               onClose: processChange,
               onSelect: processChange
            });

            scope.$watch(modelAccessor, function (val) {
               var date = new Date(val);
               element.datepicker("setDate", date);
            });

         };

      }
   };
});

/* Fragment End - directive */

References
  1. henriquat.re 
  2. Combining AngularJS with existing Components
  3. AngularJS Migrating from Previous Versions 
  4. Adding directive makes controller undefined in angular js code
  5. AngularJS versions

No comments:

Post a Comment