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.

Getting data from Angular – how close is it to stores in extjs?

I like the two way data binding that Extjs brings to the table and the fact that I can declare stores in the view model so how would I access data in angular? Turns out Angular is also built on two way data binding so you could build a set of ‘stores’ rather easily. Here’s what I ended up doing. First, using Dan Whalen’s excellent blog post on restful services I built what I would call a DataFactory. My goal was to have this ‘Factory’ behave like a store proxy in extjs – so in short I wanted to create something that worked like the api{} below.

api : {
       read      : '/getSomething',
       update    : '/updateSomething',
       create    : '/createSomething',
       destroy   : '/destroySomething '
},

So, in angular I started my ‘store’ like this:


app.factory('DataFactory', function ($http, $q) {
  'use strict';
   return {

   };
});

The function above relies on two service providers, $http, and $q. The first service $http, is pretty self-explanatory, it’s what allows us to go out and asynchronously fetch data from the server and then bind it to a variable in the controller which in turn seamlessly updates the user interface. $q on the other hand is something that I did not encounter in Ext even though the singleton Ext.defer seems to allude to $q.defer(), they are very different. $q.defer() sets your promise up with three methods that will allow it to hang around and wait until something happens – or – you decide it’s not going to happen. Ext’s defer sets up a function to run after the clock decides that something should have already happened. I’ve seen a lot of errors based on miscalculation in the Ext.defer milliseconds parameter.

On to the get method:


app.factory('DataFactory', function ($http, $q) {
  'use strict';
  return {
     get : function (url, params) {
       var   deferred = $q.defer(),
             params = { params: params };

      $http.get( url, params )
     .success(function(response)  

    var data = angular.fromJson(response);

 // Expects {success:true, data:[ ....
        if(data.success){
         deferred.resolve( response );
        } else {
         deferred.reject( data.msg );
        }
    })
    // This is an http error
    .error(function(response) {
        deferred.reject( 'Http error status code ' + response.status );
 });
           return deferred.promise;
   }
};
});

A promise is a promise

Once we declare deferred above we are automatically creating a promise. In this instance we promise to get data so we go out to the server and try to fetch the data using the $http call which will ultimately lead to one of two outcomes. First, the data could come back from the server ok (we hope) and then we would have made good on our promise and we let the app know by calling the resolve method of deferred; passing the data as a parameter. Sadly, there are instances when promises are broken, it’s happened to all of us, so in that case we notify the app of the bad news using the reject method of our deferred instance; and if we have any manners we’ll pass the reason why we broke the promise in the parameter. That’s not all; there is a third thing that happens with promises. We have all had that friend or maybe we are that friend who promises to do something but just can’t get it done in time. What do we do, beg and plead for more time, right? In that case you want to notify the page that the promise might take a little longer than expected using the notify method of your deferred instance.

So how do we call the get method of our new data factory?

Now that we have the get method defined in the DataFactory we just need to call it and pass the two parameters that have been defined:

url     : (string) required – where do you want to get the data from

parameters       : (object) optional – the parameters that you may want to pass to the server

The block of code below shows the data call. Since the factory is returning the promise we can tap into the callbacks of the then method (about halfway down – https://docs.angularjs.org/api/ng/service/$q ) . Here we are just assigning the data returned to the data variable in scope or sending an error message to the console.

DataFactory.get('/someurl').then(
 // Success Function   function(data){
       $scope.data = data;
   },

// Failure Function
   function(msg){
      console.error(msg);
   });