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.

Remap Ctrl-V, Ctrl-P, Ctrl-X

I am probably a very small segment of the population that uses the Dvorak keyboard for typing.  I switched many many years ago and haven’t looked back.  I recently was trying to see how difficult it would be to remap the cut/copy/paste keys.

Below is the script I used to remap with AutoIt –

AutoMapKey

 ; Remap ctrl copy, cut, paste.
 ; remaps the originals back to the standard english keyboard
 ^j::^c
 ^q::^x
 ^k::^v
 ToolTip You pressed %A_ThisHotkey%.
 return

AngularU Learning Notes (brain dump)

Day 1

Main Thread <– message passing –> web worker
  • restrictions using web worker – no access to dom
  • can angular and the app business logic could be in a web worker
  • Ex. ionic / onsen ui
Angular 2
  • Angular Renderer (can be ios/angular u) <– —> main js thread
  • Ex. NativeScript (cross platform framework for js applications)
  • React Native — integration between it and A2
  • Angular 1 – DOM template + Data = DOM View
  • Server-side rendering
    • Faster startup
    • SEO
    • Previews
TypeScript
Next milestones
  • Finish Core / API Sugaring / Perf+ / Docs
  • Migration Support / Animate / Material Design / CLI
    • CLI – scaffolding
  • Server Render / Native / Web Workers / ?
Slides
Q/A
Random:
Tomorrow
Angular / TypeScript
egghead.io
Showing Angular2 application
ng6 Why You Should Use ES6 with Angular Today
  • https://angularclass.com/
  • ES2015 now with Angular 1.x
  • ES6 spec is final (ES7 in the works)
  • Angular 1.x is going to be here for a while
  • JSPM uses SystemJS
    • compatible with Babel and Traceur
Webpack
  • Loads and bundles modules
  • Plugin system
  • easy setup
Useful features for Angular
  • Example ES6 class for angular today
    • export default class { constructor($http, myService) { } …
  • Gotchas…
  • It’s not completely ready and depending on the trans-compiler – need to be aware of what works and what doesn’t.
  • ebook – http://exploringjs.com/
Dominating Shadow DOM
Migrating to Angular2
  • Directive that is made more component based
  • Directive sets the things it needs through the attributes of the element controller
  • Directive does not fetch data from server.
  • Observable –
    • new Rq.ReplaySubject();
    • onNext(this.boxes);
  • David East – https://github.com/davideast/angularu-a2-migration
Dominating Shadow DOM
  • Chrome Dev Tools – setting to “Show user agent shadow DOM” (under Elements)
  • Disecting Custom Elements – Element –> Shadow Host
  • Use the createShadowDom() to create shadow dom element.
  • Terminology
    • Shadow host
    • Shadow root
    • etc.
HackStack.js: AngularJS Applications Broken APIs Delivered Late
MEAN stack
Upgrading the Web
Security
  • RFC 1738 – // user : password @ host : port / url-path (1994)
  • “The use of URLs containing passwords that should be secret is clearly uswise”
What’s wrong with the Web?
  • Insecure / Complex
  • Certificate Authorities – many have been hacked / versign, etc.
  • Document Object Model – “Worst API ever” – very hackable if you have access.
    • “I feel confident in saying the the DOM is the worst API ever created.”
  • CSS – Crappy Stylesheets
  • JavaScript – is a hot mess and it’s getting messier
  • Many Have Tried – Microsoft, Apple, Adobe, Oracle – In most cases, the technology was better but was not open and there was no transition.
  • Upgrade the Web – Keep the things it does well.
  • HDTV
  • Helper App – could have an element that if the browser doesn’t know what it is – they call another app that knows what to do with it.
  • Transition Plan
    • convince one progressive browser maker to integrate.
    • convince one secure site to require its customers to use that browser
    • Strong Cryptography – ECC 521 / AES 256 / SHA 3-256
    • ECC521 public keys as unique identifiers
    • Secure JSON over TCP – much more flexible – not just request/response
    • URL – web: publickey @ ipaddress / capability
    • Trust Management – Petnames
    • Vat – would create “Cooperation under mutual suspicion”
    • JavaScript Message Server <–> Qt
  • The Old Web: Promiscuity
  • The new Web: Commitment

Day 2

– Angular 2 Forms
– Building Office 365 SPAs with Angular and CORS
– Directives in Angular: 1 + 2 = WIN
– Componentize your app with Polymer Elements OR Foundation for Apps: Integrating AngularJS with Responsive Web Apps
– Creating d3 Components with Angular2 and TypeScript OR Angular + Cordova + Monaca = Killer mobile app development
– A Token Walks into a SPA…
TypeScript and Angular 2.0
Moving to TypeScript
  • mv files from *.js –> *.ts
  • create tsconfig.json
  • fix errors (still produces correct js files)
  • add classes
  • move to using es6 modules
Angular 2 Forms
Building Office 365 SPAs with Angular and CORS
  • Azure AD – OAuth
  • ADAL JS
    • 2 components – adal.js / adal.angular.js

From the other – https://github.com/jacobscarter/angular-crazy-fast-prototyping

Directives in Angular: 1 + 2 = WIN
Decorators
  • <div ng-click=”handlePaused()”>
  • Gives new functionality to the dom node.
Directives (A2)
  • @Directive({
    selector: ‘[blue]’
    })
    export class Blue { … }
Componentize your app with Polymer Elements
Polymer Starter Kit
Offline
A Token Walks into a SPA…
  • jwt – json web token decode/encode
  • Used decodeJWT filter
  • No state on the server for logged in or not instead we have a jwt or we don’t.
  • RouterOutlet for Angular2
  • Change from RouterOutlet to LoggedInOutlet from ‘./LoggedInOutlet’
  • http://jwt.io/
  • http://auze.ro/auth-angularu
  • @mgonto
Design+Performance

  • Speed is more important than design embellishment
  • Users expect sites to render in under 2 seconds
  • Added in-page reminders for how things are going with performance – example etsy.
  • window.onload is not the best metric for measuring website speed
  • http://www.webpagetest.org/
  • Good metrics
    • Start Render
    • Speed Index
  • Scripts and css have a higher priority
  • Can have scripts labeled async and then they won’t have the high priority to the browser
  • gzipped?
  • custom metrics – define most important elements on the page
  • http://stevesouders.com/talks
  • @souders
  • https://developers.google.com/web/fundamentals/performance/critical-rendering-path/index?hl=en

 

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.

How to Change Windows 8.1 Network from Public to Private

Came across this recently and found many different avenues for fixing this problem.  Out of the one’s I found – the solution below worked the best for me as I especially liked that it didn’t involve tweaking the registry:

Set-NetConnectionProfile -InterfaceAlias “Wi-Fi” -NetworkCategory Private

  • Before running make sure the PowerShell is run as an administrator
  • “Wi-Fi” will be your network adapter you are trying to access to change.

If you need to get your connection information (Yours will probably be called something other than “Wi-Fi”):

  • Start a PowerShell as an Administrator
  • Run: Get-NetConnectionProfile

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.

Thinking About Strategy in Implementation

I was told this story by a friend.  I am not sure where it originates (found this possibly reference). Good story to ponder:

Three programmers were asked to cross a field and go to the house at the other side.

The novice programmer looks at the short distance and says, “it’s not far!. That will take me ten minutes”

The senior programmer looks at the field, thinks for a while and says “I should be able to get there in a day”. The novice looks surprised.

The ninja programmer looks at the field and says. “Looks like ten minutes, but I think fifteen should be enough”. The senior programmer sneers.

The novice programmer sets off, but within a few moments, explosive land mines go off, blasting huge holes. Taking him off course, and requiring him to double back and attempt the crossing many times. It takes him two days to reach the goal. Although he is shaking and injured when he arrives.

The senior programmer sets off on all fours. And carefully taps the ground searching for mines, proceeding only when it is safe. Slowly and meticulously he crosses the field over the course of the day. Only setting-off a couple of mines.

The ninja programmer sets off, and walks directly across the field. Purposefully and directly. He arrives at the other side in just ten minutes.

“How did you do it”?, the others ask. “How come the mines didn’t get you?”

“Easy” he replies. “I didn’t plant any mines in the first place”.

Using Genymotion with Ionic (Cordova, PhoneGap)

Just a quick tutorial here.  I have been using this great Ionic Framework for creating hybrid apps with AngularJS.

Genymotion is a piece of great software for Android developers. It has one of the fastest emulators out there, and now that I know about it, I can’t even imagine developing Android apps without using it. One of the things that make it stand out is that it uses Virtual Box under the hood.

Ionic has a command line for running the app on the emulator, iOS or Android. Just call ionic emulate android and it will fire up an emulator and install the app. Unfortunately, it couldn’t find the Genymotion emulator! Whhhhyyyyy?!

The issue is that it’s not Ionic or Cordova, the real thing that is called behind the scenes.  It’s because Genymotion doesn’t tell android-adb that it is an emulator. It tells that it is a device.  After realizing this – it makes sense.

We need to run as a “real device”. To do that we need to run:

ionic run android

Now it will find the Genymotion Virtual Android and everything will work.

Enjoy!

Error code: ERR_UNSAFE_PORT

This is because of Chrome restricting the local ports.

To fix the issue:

Right click on the chrome shortcut -> Properties -> Change the target:

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --explicitly-allowed-ports=81,84,87