Materials Angular is Destroying Tab Content

By default materials angular library (materials.angular.io) will destroy the tab content between tab selection changes.  This is usually what people would want though in our case we have a webview (essentially an iframe) that needed to be embedded into the tab.  Every time a user switched tabs the iframe content would be lost as it re-renders from scratch.  We also didn’t like how the scroll bar was reset because of the re-rendering of the tab.

Here is a demo using the materials mat-group and mat-tab components.  To show that the tab doesn’t get reset you can click “play” on the video and then click the other tab and go back.

Working demo: https://angular-tabs-material.stackblitz.io

The main code is having a separate ngFor loop which sits outside of the mat-tab-group component.  In the future, I hope to understand if there is a configuration or override option to the mat-tab-group though this allows us to continue to move forward.

<mat-tab-group (selectedTabChange)="selectionChange($event)">
  <mat-tab *ngFor="let tab of tabs; trackBy:trackByFunction"label="{{tab.tabName}}">
  </mat-tab>
</mat-tab-group>

<div>
  <div *ngFor="let tab of tabs; trackBy:trackByFunction">
  <div [hidden]="currentTab.tabName !== tab.tabName">
    {{tab.tabName}}
    <iframewidth="100%"height="100%" [src]="url"></iframe>
  </div>
</div>

The [hidden] will hide the content for the tabs that should not display. This is different from the *ngFor which will remove the content out of the page.  We have to be careful about how the [hidden].  This is true for browser memory, page rendering time, etc.

Day 1 of NG-CONF 2016 – Links!

I haven’t decide which I like more – Angular 2 or React – both amazing frameworks!  Here are the links I recorded down from the many sessions on Day 1.

Chrome tool
https://augury.angular.io/

Style guide & Resources
https://angular.io/styleguide
https://angular.io/resources/

Mobile
http://mobile.angular.io/

Electron App
https://www.npmjs.com/package/electron-angular-boilerplate

Material 2
https://github.com/angular/material2
http://valor-software.com/ng2-bootstrap/
https://material.angularjs.org/latest/

Kiva – Micro Loans
https://www.kiva.org

Native Script
https://www.nativescript.org/ng-conf

Lucid software chart
http://lucidchart.com/ngconf

Angular Server Side Rendering
https://github.com/angular/universal

Microsoft Code
https://code.visualstudio.com/Docs/?dv=win

Angular CLI
http://cli.angular.io/

Angular Style Guide
jpapa.me/ng2styleguide

Dan Wahlin
Type script snippets: http://tinyurl.com/ng2Snippets

Google says 250ms can make a big difference in user bounce rate

Horizon / Rethinkdb
http://horizon.io/
https://www.npmjs.com/package/horizon

Angular 1.5.x Components
https://github.com/petebacondarwin/ng1-component-demo

SailsJS with Swagger UI

Recently wanted to use Sails JS framework which runs on Node.  I have heard a lot about it and wanted to check it out.  I also wanted to be able to use swagger-ui with it.  I saw the plugin available but ran into a glitch.  This should be resolved *hopefully* soon.  In the meantime if you want them to work together here is what one will need to do:

—–

Since I am not running off master for either project. I combined comments from this thread and hope it helps others:

1) npm install –save lodash

2) Created the controller


1
2
3
4
5
6
7
8
9
// api/controllers/SwaggerController.js

var _ = require('lodash');
var _super = require('sails-swagger/dist/api/controllers/SwaggerController');

_.merge(exports, _super);
_.merge(exports, {
  // Extend with custom logic here by adding additional fields, methods, etc.
});

3) Created the installHooks.js


1
2
3
4
5
6
7
// config/installedHooks.js
module.exports.installedHooks = {
  "sails-swagger": {
    // load the hook into sails.hooks.swagger instead of sails.hooks['sails-swagger']
    "name": "swagger"
  }
};

4) Create swagger.js hook:


1
2
3
4
5
6
7
8
9
10
// config/swagger.js
module.exports.swagger = {
  /**
   * require() the package.json file for your Sails app.
   */
  pkg: require('../package'),
  ui: {
      url: 'http://swagger.balderdash.io'
  }
};

5) Downloaded swagger-ui and copy the dist/ contents to assets/docs under my current webapp. I am sure using docker works well but I didn’t try it as I wanted it all under the same app.

6) Done. (At least I hope I got everything).

Protractor – Timed Out After 11 Seconds – Continuous Polling

Timed out waiting for Protractor to synchronize with the page after 11 seconds. Please see https://github.com/angular/protractor/blob/master/docs/faq.md

When first trying to setup protractor, I came across this error which is well described in the aforementioned link.

It mentions, if your application continuously polls $timeout or $http, it will never be registered as completely loaded. You should use the $interval service (interval.js) for anything that polls continuously (introduced in Angular 1.2rc3).

This makes complete sense.  In the app that I am currently working on, there is legacy code which needs to be rewritten in order to achieve the use of $interval.

For now, I want to do a proof-of-concept without re-writing code.  So in this case, a timeout is used in order to do continuous pulling.

The temporary solution I used was “browse.executeScript()” function available with protractor.  Since we are able to access angular, we can go and get the service and stop that service.  This then allows protractor to know the page is initially done loading since there are no longer any JavaScript timeouts left.

 

var injector = angular.element(document.body).injector()
var service = injector.get(‘SomeService’);
service.stop();

 

Story for backlog – using $interval instead of $timeout in polling service.

Parsley Validation with AngularJS

This is a quick post on how I was able to get ParsleyJS validation working with AngularJS.  I used Parsley.js 2.x and Angular.js 1.3.x and 1.4.x.

How to use it

Then all you need is to add “parsley-validate” to your form element as an attribute and then parsley will be tied to that form.

For example:
<form parsley-validate>
  <!-- normal form elements here -->
</form>

Note

  • Will load parsley when the form is loaded from angularjs.
  • This takes care of the dynamic inserting of forms into the page.

Code

var angularParselyModule = angular.module('parsley', []);

angularParselyModule.parsleyOptions = {
  priorityEnabled: false,
  errorsWrapper: '<ul class="parsley-error-list"></ul>'
};

angularParselyModule.directive('parsleyValidate', ['$timeout', function($timeout) {
  return {
    restrict: 'A',
    require: '?form',
    link: function(scope, elm, attrs, formController) {
      elm.bind('$destroy', function() {
        formController.parsley.destroy();
      });

      if(!formController.parsley) {
        formController.parsley = new Parsley(elm[0], angularParselyModule.parsleyOptions);
        $timeout(function() {formController.parsley.validate()}, 100);
      }

      scope.$on('feedReceived', function() {
        if(!formController.parsley) {
          formController.parsley = new Parsley(elm[0], angularParselyModule.parsleyOptions);
        }
        formController.parsley.validate();
      });
    }
};
}]);

//We register our parsley logic for various element types.
angularParselyModule.directive('input', parsleyFieldDirective);
angularParselyModule.directive('textarea', parsleyFieldDirective);
angularParselyModule.directive('select', parsleyFieldDirective);

function parsleyFieldDirective($timeout) {
  return {
    restrict: 'E',
    require: '^?form',
    link: function (scope, elm, attrs, formController) {

      if(formController.parsley) {
        $timeout(function() {formController.parsley.validate()}, 150); // Need to validate after the data is in the dom.
      }
    }
  };
}

Final Thoughts

Now with AngularJS 1.3+ we have much better form validation. The benefit of ParsleyJS is that it allows for messages to be reused much more easily then even in the new Angular 1.3. Since the Angular forms are much better integrated with HTML5, I ended up moving in that direction. In order to reuse the messages, ngMessage module can be used with Angular and is much better at reuse though, I made some slight changes to make it even more reusable. Hopefully I will share that in another post.

Auto Response for Testing Node.js SaaS Based REST API

I have been enjoying the use of Node.js.  I started by first creating the backend which is a node.js server which has REST end-points that my client will call.  In this case the client is a mobile application to receive data on tweets.  That isn’t necessarily important for this short post.

I was at a coffee shop recently and really didn’t want to ping my node.js test server each time I was working on the client.  I used Fiddler to create an auto-response that would usually come back from the node.js server.

Fiddler Auto Response

1. In the picture you can see that I have right-clicked on the request to save the response.

2. Click on the AutoResponder tab.

3. Then insert your the response url you want to auto repsond to.  Add in the file location to the response you saved from the last step.

4. I clicked the check box above which allows other traffic to pass through so that I could still go to other websites.

Sencha Touch 2.2.1 Update from 2.0.x

Few things I encountered as I was updating to the latest version.  Hopefully this can help others:

Error: com.sencha.exceptions.ExProcess: compass process exited with non-zero code:1

  • Make *completely* sure you have ruby 1.9.3 installed and not 2.0.0.  If on windows use this installer.
  • Install compass from gem (ie. gem install compass).  Don’t install from node.js package manager.

Error: File not found or cannot be read: sass/stylesheets/fonts/pictos/pictos-web.woff

Error: Sass::SyntaxError on line [“190”] of C: Undefined variable: “$theme-name”.

  • If you re-used the “&.popular” selector you need to remove it now.

Erply Inventory Registration – Automatically Scan Each Item

We wanted to just continue to scan each piece of inventory without having to interact with the computer from Erply.  On the Inventory Registration page, When you enter a barcode number a drop down box is displayed with one item. Erply, by default, will not select it automatically but waits for you to select.  Once the page refreshes (which I wish it didn’t), it puts the focus on the price box.  The way we want to work is just to continue scanning and come back later to fill in price.  This script is the solution for us in this use case.

Script Download: http://userscripts.org/scripts/show/151067

Script Description:

This helps in inventory registration for Erply. If you are scanning your items into Erply this script helps by automatically clicking on the one barcode dropdown that is selected and then once the page reloads it selects the next open text box ready for you to scan another barcode.  By default, Erply will wait for keyboard input for you once you scan an item.

Details

Below is a picture.  If the script is installed correctly then you will see a fish in the upper right corner of the screen.  This means that the script is installed and working on the inventory registration page.

Next thing to do is start scanning away!

You will notice one you start scanning that the drop-down will appear for a moment and then the script will select the only one listed.  The page will quickly refresh and then the script will select the bottom barcode/name box.

Let me know if you have questions!

Printing Labels from a Zebra LP2824 Printer in Erply

We are beginning to use Erply system for inventory. By the way, it is a fantastic system! Anyway… we were wanting to get the Zebra LP2824 Plus printer working here in Haiti.  Unfortunately, at this time of writing, there wasn’t an option to print a 2 1/4″ x 1/2″ label in Erply.  No problemo!

Erply recommends that you use Firefox (which is a great browser – I happen to switch between Google Chrome and Firefox).  So if you are using Firefox then you can head over and install Greasemonkey addon.

Then you can install the greasemonkey script for printing the barcode labels:

http://userscripts.org/scripts/show/138788

To use: You will need to pick “Barcode label (90mm x 14mm). The next page will automatically size the image and barcodes to fit the 2 1/4″ x 1/2”.

This script makes the label large enough so that the iPad Point of Sale application will be able to scan the barcode printed. Most barcode scanners will work but the label wasn’t large enough for the iPad to scan it.

Details:

– This script is made specifically for printing only EAN-8 labels. If you want to print EAN-13 you will need to adjust the script manually.

– Won’t work if you want to print the mass of the item on the label.

Sencha Touch 2 Showing Old Data After Refresh on Production

I am not totally understanding why even after updating production and seeing the correct delta’s that I am seeing the old site information.

For now: I have figured out that you can clear the local storage in google chrome (very easy to do).

On my andriod device I needed to do the following in the browser url bar:

javascript:localStorage.clear();

This would then allow me to see the newest production site.

I am hoping this problem is because I have been messing around and deleting the production base. Guessing I will learn more once I get closer to actually putting it in production!