Google

Sep 12, 2013

Working with Angular JS and jQuery UI : resizable TextArea to overcome IE limitation

AngularJS is a popular MVW (Model View Whatever) framework. Recently had an opportunity to test drive Angular JS for GUI development retrieving data via RESTful web service calls. The JavaScript based GUI frameworks like Angular JS, Backbone, etc will becom more poular and replace JSF. So, it really pays off to lean AngularJS if you like developing GUIs. If you go to YouTube, you will find a number of good beginner's tutorials to get started.


Q. What is a directive in AngularJS?
A. Directives extends HTML. During DOM compilation directives are matched against the HTML and executed. This allows directives to register behaviour, or transform the DOM. ng-app, ng-controller, ng-model, etc are directives. The directives can be placed in element names, attributes, class names, as well as comments. Directives are defined with camel cased names such as ngApp and invoked by translating the camel case name into snake case with these special characters :, -, or _. For example ng-ap p as in <html ng-app>




Q. When do you need to create your own directives?  How will you go about creating a custom directive in AngularJS?
A. There are instances where you want to use jQuery UI plugins. Reecently, I had to use the the jQuery Resizable plugin with angular to resize my TextArea in IE 8 as it is the standard browser used by our business and operational staff. Here are some code samples to get AngularJS and jQuery to work together.  By default, the Angular JS is shipped with a lite version of jQuery, but not with the UI plugins.



Step 1: You need to define directives.  Directives are a way to teach HTML new tricks. During DOM compilation directives are matched against the HTML and executed. I am using RequireJS to manage dependencies. here is myTextAreaWithModel.js file


'use strict';

define([ 'jqueryui' ], function() {

 
 function myTextAreaWithModel() {
  return {
   require: 'ngModel',
   // Restrict it to be an attribute in this case
   restrict : 'A',
   // responsible for registering DOM listeners as well as updating the
   // DOM
   link : function($scope, $element, $attrs) {
    jQuery(function() {
     jQuery("textarea.resizableAreaWithModel").resizable();
    });
   }
  };
 }

 return myTextAreaWithModel;
});


Step 2:  A sample bootstrapping JS file that uses require js to manage dependencies. The key here is to see how jquery-ui is loaded. You can choose to ignore the rest.

'use strict';

/**
 * Configure JS file paths and dependencies
 */
var requireConf = {
    baseUrl: '.',   // This will be the path to portal.html
    shim: {
        'angular'             : { deps: ['jquery'] },
        'jqueryui'            : { deps: ['jquery']},
        'bootstrap'           : { deps: ['jquery'] },
        'portal/portalCtrl'   : { deps: ['angular'] }
    },
    paths: {
        jquery    : 'lib/jquery/jquery',
        jqueryui  : 'lib/jquery/jquery-ui',
        angular   : 'lib/angular/angular-module',
        bootstrap : 'lib/bootstrap/js/bootstrap',
        text      : 'lib/require/plugins/text'
    },
    waitSeconds: 0,                 // Disable the RequireJS timeout
    urlArgs: ((myapp.debug) ? '' : 'v=' + (((new Date()).getTime() + '').substr(2,8)))   // URL cache breaker changes every second - TODO: use a version number instead : '';
};

require.config(requireConf);

/**
 * Load JS resources for the portal (but not for apps), then bootstrap Angular.
 */
require([
    'jquery',
    'angular',
    'portal/portalCtrl',
 
], function (jq, angular, portalCtrl) {

    angular.element(document).ready(function() {

        // Load the root controller for the page
        angular.module('portalModule.controller', [])
            .controller('portalCtrl', portalCtrl);

        // Load all angular style resources
        angular.module('portalModule', [
            'portalModule.controller',
            'portalModule.directives',
            'portalModule.services',
            'portalModule.filter'
        ]);

        // Bootstrap angular, this needs to be after the html page and the various JS resources defined above have loaded.
        angular.bootstrap(document, ['portalModule']);
    });
});


Step 3: Bootstrapping the "myTextAreaWithModel" using require js framework.

'use strict';

define([
    'angular',
    'utils/directives/myTextAreaWithModel'
], function (angular, myTextAreaWithModel) {

    angular.module('portalModule.directives', [])
         .directive('myTextAreaWithModel', myTextAreaWithModel);
});


Step 4: Finally the HTML code.

    ....
 <td width="30%">
  <textarea class="resizableAreaWithModel comments" 
     name="comments" ng-model="myAppStatus.comment" 
     jp-text-area-with-model 
  />
  </td>
  ....


Directives in angularjs are very powerful.


Labels: ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home