Bringing code consistency to the team – Some thoughts on developing using Dustin Specker’s AngularJs generator

Some concepts you may have gotten away with in the past will not work going forward and that is not a bad thing.

This framework assumes that you are very familiar with John Papa’s Angular Style Guide – If you are not I would suggest reading it front to back at least once because the boilerplate code that is produced will look a lot like the code in this guide and expect that you fill it in with code that follows the guidelines in this file. Not doing so may will result in code that does not run. For example when you take a look at the code for the socket factory from html5rocks.com, you may think great! You may run it and still feel pretty good, however, you might decide to move it over and notice that it fails – completely, let’s take a look at what went wrong:

app.factory('socket', function ($rootScope) {
  var socket = io.connect();
  return {
    on: function (eventName, callback) {
      socket.on(eventName, function () {  
        var args = arguments;
        $rootScope.$apply(function () {
          callback.apply(socket, args);
        });
      });
    },
    emit: function (eventName, data, callback) {
      socket.emit(eventName, data, function () {
        var args = arguments;
        $rootScope.$apply(function () {
          if (callback) {
            callback.apply(socket, args);
          }
        });
      })
    }
  };
});

The corrected function will then look like this:

(function () {
  'use strict';

  /**
   * @ngdoc service
   * @name newProject.factory:Socket
   *
   * @description
   *
   */
  angular
    .module('newProject')
    .factory('Socket', Socket);

  function Socket($rootScope, $timeout) {
    
    var SocketBase = {
        on   : on,
        emit : emit,
        init : init
    };
      
    return SocketBase;
      
    function on(eventName, callback) {
          $rootScope.socket.on(eventName, function () {  
            var args = arguments;
            $timeout(function() {
              callback.apply(Socket, args);
            }, 0, false);
          });
    };
    
    function emit(eventName, data, callback) {
          $rootScope.socket.emit(eventName, data, function () {
            var args = arguments;
            $timeout(function() {
              if (callback) {
                callback.apply(Socket, args);
              }
            }, 0, false);
          })
    };
    
    function init() {
      $rootScope.socket = io.connect(); 
    }; 
  }
}())

Directives and scope – what you don’t know can burn you later – The boilerplate code that is generated by the framework includes a standard directive definition object (DDO). The default value for scope in the definition is {}. This means that a new isolated scope is created for the directive which does not inherit from the parent scope. If you intended for the definition to read or write to the parent scope then this will not work.

Beware of the Angular Digest Cycle – You may start to notice that the error $apply already in progress will begin to enter your app at places where in the past the code seemed to run fine.

The following block of code that is executed in the emit function produces the error when used in the framework.

$rootScope.$apply(function () {
  if (callback) {
    callback.apply(socket, args);
  }
});

Per the suggestion on the Angular API above and again conforming to the Angular Wrapper Services found here rewrite the code by replacing the apply with a timeout service to force the callback to run asynchronously. It also helps to be more judicious in your use of $rootScope.

$timeout(function() {
  if (callback) {
    callback.apply(Socket, args);
  }
}, 0, false);

Get familiar with the difference between E, EA and A in your directives

Mind your versions – We’ve all been conditioned to keep clicking next in order to get through tiresome EULAs so you may be tempted to skip right through the framework setup without considering the versions of the dependencies that are being loaded. All of your versions are in the bower.json file in the root of your project, here’s a sample from a default build:

{
“name” : “newProject”,
“version” : “0.0.0”,
“dependencies”: {
“angular” : “~1.3.*”,
“angular-animate” : “~1.3.*”,
“angular-aria” : “~1.3.*”,
“angular-route” : “~1.3.*”,
“angular-sanitize”: “~1.3.*”,
“angular-material”: “~0.8.0″,
“lodash” : “~2.4.1″,
“polymer” : “Polymer/polymer#~0.5.0″,
“core-elements” : “Polymer/core-elements#~0.5.0″,
“paper-elements” : “Polymer/paper-elements#~0.5.0″,
“moment” : “~2.10.3″,
“pleasejs” : “~0.4.2″
},
“devDependencies” : {
“angular-mocks” : “~1.3.*”
}
}

At the time of generation lodash was on version 3.9.3, or a full version above so any use of methods that exist in the new version will not work correctly in the default version. How do you update bower packages? Since you have versions in the file above running $bower update lodash, for example will continue to bring down version 2.4.1, so just change the version in the file to the targeted version and run the update command. Reload your browser and locate the file in the Network tab on Chrome’s dev tools and see if the version is what you were expecting.

Watch your bower.json and .bower.json files, three things to consider1) Adding new bower dependencies requires you to run gulp dev, and if you look into the gulp/build.js file you can see where everything is wired up to copy the files that reside in the projects bower.json file which is found at the top level (root) folder of your application. 2) Not every package comes with a clean bower.json file one of the issues you might find is that the “main” property in the individual packages may be prepended with a ./; for example, the snippet below would not be carried over into the build folders and will result in a 404 error when loading this in the browser. (I found that sometimes what you see in git is not what is downloaded by bower as well?) 3) It’s imperative that you run –save after your bower command to make sure that the file is added to your projects bower.json file. If in doubt look into that file to verify that you are indeed requiring the dependent file!

{
“name”: “pleasejs”,
“version”: “0.4.2”,
“homepage”: “https://github.com/Fooidge/PleaseJS”,
“authors”: [
“Fooidge”
],
“description”: “JS library to generate random pleasing colors/color schemes”,
“main”: “./dist/Please.js”,

Changing Styles on IE11 with angular in a {{bind}}

You may be tempted to use ng-style directive (https://docs.angularjs.org/api/ng/directive/ngStyle )or even to try and render part of the style in the tag itself like color:{{myColor}}, however, if you go back and test any of these methods on IE11 you will quickly see that they do not work and viewing the source reveals the binding – curly braces and all in the elements style attribute. The only way to get this working on both chrome and IE for me was to use the ng-attr-style directive. This even takes the complete style string like “color:red”.

Angular’s ui-bootstrap; how to pass variables to your $modal windows

I downloaded UI Bootstrap from https://angular-ui.github.io/bootstrap/ to use as the primary ‘theme’ if you will for a recent angular project. One of the directives that I needed right away was the Modal so that I could make a few components that I knew I needed, like an error message dialog that displayed the error messages from Ajax calls to the end user. The documentation did not really spell out how to pass variables to the scope of the modal controller so hopefully this will be of help if you are using the same component and working on the same issue.
Add the value to the resolve config in the modal open function call.

$modal.open({
            templateUrl : 'app/shared/partials/error_modal.html',
            controller  : 'ErrorController',
            size        : 'lg',
            resolve     : {
                errormsg : function () {
                        return response.msg ;
                }
            }
});

Now for the controller; here it is important to inject the variable into the function. In the code below you can see that errormsg is the same variable that is resolved in the open function above. The response.msg variable is present in the scope of the calling page.

app.controller('ErrorController', function ($scope, $modalInstance, errormsg) {
    $scope.errormsg = errormsg;
    $scope.cancel = function () {
        $modalInstance.dismiss('cancel');
    };
});

Finally, the html that makes up the modal window is here so that you can get a full picture of what an error modal window looks like:

<div class="modal-header">
    <h3 class="modal-title">There was a problem ....</h3>
</div>
<div class="modal-body">
    {{errormsg}
</div>
<div class="modal-footer">
    <button class="btn btn-success" ng-click="cancel()">Ok</button>
</div>

Some things I wish I knew about JointJs before building an interactive JavaScript flow chart

Recently I spent a great deal of time drawing a flow chart and wiring up several events using jointjs (http://www.jointjs.com/ ) to allow users to update the underlying record behind the chart by clicking an element. I decided to use JointJs to accomplish this task as it seemed to have all of the elements that I wanted, plus a pretty easy to read API – which arguably is the best feature of any library. However, even with all of the resources provided I had to do a lot of digging into the API, sample code, and spent far more time than I want to admit on stack exchange to accomplish this. I thought I would summarize the things that I wish I had known before starting out:

Adding custom variables to chart elements:

The first thing needed was the ability to add custom variables to my chart elements because I wanted to provide some interaction with the backend on click and to do that I wanted to pass keys back and forth from the chart.


var someExampleChartBlock = new joint.shapes.devs.Coupled({
    position: { x: 75, y: 100 },
    size    : { width: 50, height: 50 },
    inPorts : ['In'],
    outPorts: ['Out'],
    prop    :{

    data : {'attr1' : 'some', 'attr2' : 'custom', 'attr3': 'variables'}

    },
    attrs: {
        '.label'            : { text: 'Box', 'ref-x':.5, 'ref-y': -20 },
        rect                : { fill: '#d9534f' },

        '.inPorts circle'   : { fill: '#16A085', magnet: 'passive', type: 'input',r:'3' },
        '.outPorts circle'  : { fill: '#E74C3C', type: 'output',r:'3' }
    }
});

 

Once you add the custom variables to your elements the next thing you probably want to do is access them so to add a click event to elements on your chart (paper) then just use the following function. The API does coincidentally have a really good list of events that you can listen for here: http://jointjs.com/api#joint.dia.Paper:events . The code snippet below shows you how to access the values in the custom variable that you made above.

 


/*

Assumes that you set up your

 paper with the name paper
var paper = new joint.dia.Paper({
…….

});

*/

paper.on('cell:pointerdown',
   function(cellView, evt, x, y) {
          console.log('Your custom variables live here :' , cellView.model.attributes.prop);
     }
);

Updating the chart elements:

I also noticed that once the chart had been rendered the last thing you wanted to do was redraw the elements to update them as it would literally add new elements on top of the old. I was changing colors of blocks based on the data coming back in an Ajax call so once the data comes back I just call a simple function to change the color of the element, for example.

someExampleChartBlock.attr({
    rect: { fill: '#SomeOtherColor' }
});

Remove the ability to move elements around and make the cursor a pointer:

I can see a use case for moving the elements on the paper but unfortunately, in my application I wanted the chart to remain static so I needed a way to turn off the user’s ability to remove links and drag elements around. This can be done with the following CSS pretty easily.

.link-tools .tool-remove path {
    display: none;
}

.link-tools .tool-remove circle {
    display: none;
}

.element , .link-tools, .marker-arrowheads, .marker-vertices {
    cursor: pointer;
    position: fixed;
}

.element * , .link-tools *, .marker-arrowheads *,  .marker-vertices *{
    vector-effect: non-scaling-stroke;
    -moz-user-select: none;
    user-drag: none;
    position: fixed;

}

.element:hover{
    background-color: #428bca;
}

 

Some thoughts on Angular from an Extjs developers perspective

Up until now I have been blogging primarily on Extjs and maybe a few other tasks like Sql Server, SSIS, and Adobe forms. I’ve been using Extjs since the beginning of version 2 and have grown to really appreciate it for what it can do for a large project developed by a small Dev team. That said I’ve been cognizant of the fact that there are a lot of other frameworks taking off right now; but – and this is key – I am old enough to have seen a lot of ‘next big things’ start with a bang and slowly fade away. Would you believe that at one point the future of the internet was going to be Java applets? That said I could no longer ignore one of the more popular frameworks, Angular.js; and I have finished toying with the idea of rewriting one of the apps I work on using this framework and actually started the rewrite.

Full disclosure – I am only taking this path because the user interface is set to become more ‘dashboard / data display’ and less of what some would consider an ‘app’ – you know where people enter a lot of data and stuff like that. I don’t think you should try and recreate an Extjs app in angular unless you have to but that’s for another post. I also know it’s a fool’s errand to argue the merits of either as in the end they are mere tools so the focus here is to come at Angular with an Ext perspective and just point out the differences that I see and how I overcame them.

With that said here are the first things that I noticed when stepping into angular.

Setting up your application:

I am really used to using Sencha command and love the fact that it builds a standard application straw man if you will with just three short words (no not I love you) and a command line terminal. The closest thing I could find were the various ‘starter’ apps that exist on GitHub and a link in the Angular documentation so I took liberty with the ‘W’ in MVW (Model-View-Whatever) which angular tags itself as being and set up my structure to mirror what I would find in Extjs 5’s MVVM.

This has worked out well because our developers are used to seeing this structure. So I went with a partials folder and in this folder I placed subfolders that contained the view (.html file) the controller, and I created a factory named ‘DataFactory’ that handles the requests for the controller, if you are an Extjs 5 developer you could almost view this as the view model (https://docs.angularjs.org/guide/providers).

How can I achieve something like layout: border and a viewport?

One of the first things I did was look for something that would resemble a viewport with a west panel and a center panel – why? Simple, our users have been conditioned to the layouts found in Ext for over 6 years now so any drastic change would be met with resistance; I had to make small changes. I found what I was looking for with the ui-layout module which you can find here: https://github.com/angular-ui/ui-layout .

What about grids?

I love the Extjs grids and wanted to find something comparable in angular. The caveat here is that I rarely use all of the features like row locking, inline editing and so forth. I know all of that is possible but I just needed a paging grid with sortable columns, I would do a remote filter on the data but that is just a matter of connecting a function to a textbox above the grid. There are several to choose from but in the end I decided to use Lorenzo Fox’s Smart-Table module which can be found here: http://lorenzofox3.github.io/smart-table-website/

Right about now you should start seeing a pattern, mainly much of what you need to accomplish using angular requires third party plugins, or extensions if you will. That’s great for the flexibility – I love it. That’s not so great for standardization / documentation / and building something that will not become a nightmare to maintain. If you have a really keen eye you will have picked up something else, all of the plugins listed above assume that the user is building an application that will run on the latest browsers / there is often very little (read none) support for legacy browsers – so if you are in a large organization on a corporate site (read enterprise) then you probably want something like Extjs.

The next post in the list will take a look at how I handled a ‘store’ like function in Angular.js.