js: angular touch delay/lag on mobile

I had built InviteAgain.com to seamlessly work on mobile devices. This was the first project in Angular where I wasn’t handling my own mouse/touch up and down, and I just planned to rely on ng-click, and default mouse/touch behaviors to handle the table scrolling.

I was getting what felt like bad lag when running the app on mobile. The connection to the database would load and refresh data immediately, but the user interaction, ie touch, was taking forever to respond. So after some head bashing, I managed to learn the hard way that the library angular-touch, made by angular, is pretty much a requirement for mobile if you are going to rely on ng-click, and not handle your own mouse up and down.

Angular-touch modifies the standard ng-click to remove a 300ms delay mobile browsers otherwise impose while waiting to see if the user is going to double tap. Problem solved!

js: parsing csv files in angular with papa parse

I’ve been trying to embrace/balance using more libraries and less native code. The CSV parsing I needed to do on InviteAgain.com was a great candidate. I found PapaParse. Perfect. Simple javascript class that can handle all use cases via a single settings object.

I setup an Angular directive and template that I can plug in anywhere to get a custom file input UI. That UI contains another directive linked to the file input event. On file input angular hands the csv off to the Papa object. I tell it the data has headers, to use web workers, and to run $apply() on the scope after it’s completed parsing the file. Papa hands me back a javascript object with all the csv’s key/value pairs. Done.

.directive('onReadFile', function ($parse) {
  return {
    restrict: 'A',
    scope: {conSec: '=', current: '='},
    link: function(scope, element, attrs) {
      element.on('change', function(onChangeEvent) {

      var file = (onChangeEvent.srcElement || onChangeEvent.target).files[0];

       Papa.parse(file, {
          header: true,
          worker: true,

          complete: function(results) {
            if(scope.conSec.name){
              scope.conSec.fileInput.err = results.err;
              scope.conSec.fileInput.data = results.data;
              scope.conSec.fileInput.meta = results.meta;
              // Need to force the update
              scope.$apply();
            }
          }
        });
      });
    }
  };
})

.directive('fileInput', function(){
  return {
    restrict: 'E',
    scope: {conSec: '=', current: '='},
    templateUrl: "../templates/fileInput.html"
  };
});