12/29/16

Unit Tests With Typescript

Hi lovely people my-gs500-blog-readers! I'm so glad to meet you again!
Today i want to speak about unit tests. Yes, a already wrote some series about unit testing angular1 directives, but now it is slightly different.
Why? Because i'm talking about angular typescript project.
Remember this angular-seed repo, we learned how to translate it to typescript(in this post)?
So, since the project is now contains only typescript (.ts) files - current tests would not work anymore (Because all the code that tests should be testing is not exists yet, it need to be transpilled to javascript)

Translate The Tests To Typescript

First thing to start with - lets translate all the tests to typescript: This is very simple, instead of:


'use strict';

describe('myApp.version module', function() {
  beforeEach(module('myApp.version'));

  describe('version service', function() {
    it('should return current version', inject(function(version) {
      expect(version).toEqual('0.1');
    }));
  });
});


now it is:

import * as angular from "angular";
import "angular-mocks";
import "phantomjs-polyfill";
import {version} from './version'
describe('myApp.version module', () => {
  beforeEach(angular.mock.module('myApp.version'));

  describe('version service', () => {
    it('should return current version', () => {
      expect(version).toEqual('0.1');
    });
  });
});

Not a big difference, right?

Karma Is A Bitch

Next things we need to change karma.conf file, to explain to karma: "you should load ts files now, baby"


...
files: [
    './node_modules/phantomjs-polyfill/bind-polyfill.js',
    './app/test.ts'
]
...


Processing With Webpack

For convert ts files to ES5 you need to use some transpiling tool, for example webpack:


    ...
    plugins: [
      require('karma-webpack'),
      require('karma-sourcemap-loader'),
      require('karma-jasmine'),
      require('karma-phantomjs-launcher'),
      require('karma-chrome-launcher')
    ],

    webpack: webpackConfig,
    webpackMiddleware: {
      stats: { chunks: false },
    },


    ...

For full code look in this repo

12/25/16

Add Ajax Request Indicator

Some times it is good practice to notify user that due to his actions (like sending the contact us form) some ajax request been sent and it is been processed. If you not reckon with nprogress angular lib yet, this good opportunity to introduce it... This library is angular implementation of nprogress jquery plugin, and its showing very nice loading bar on top of you application:

How to make it shown only if some ajax request made?

If you don't want to track any other requests like js and css files, only data requests to backend, it may be done by watching pendingRequests property of $http angular service:


myApp.run(function ($rootScope, $http, ngProgressFactory) {
        $rootScope.progrs = ngProgressFactory.createInstance();
        var progresstarted, progressbar = $rootScope.progrs;
        $rootScope.$watch(function() {
            var onlyJsonRequests = $http.pendingRequests.filter(function(r){return r.url.match(/json/g);});
            return onlyJsonRequests.length;
        }, function(n) {
             
            if(n>0 && !progresstarted) {
             
                progresstarted = true; 
                progressbar.setColor('blue');
                progressbar.setParent(document.getElementById('mainContainer')); //set a custom container, otherwise will be attached to "body"
               
                progressbar.start();
            } else if(n===0 && progresstarted) { 
                progressbar.complete(); 
                progresstarted = false;  
            }
        }) 
}) 

Notice that progress bar will be shown only if requests with url property that contains /json/ are sent

Provider is Better

Currently we have a lot of logic inside our run section.
One thing that can make the code more accurate is to move the progress logic to provider recipy:


myApp.provider('progress', function($provide, $injector) {
  this.setPattern = function(pattern) {
    this.pattern = new RegExp(pattern,'g');
  };
  this.setContainer = function(container) {
    this.container = container;
  };
  this.setColor = function(color) {
    this.color = color;
  };
  //will fire when used in one of recipies like "controller" or "directive" or "run"
  this.$get = function ($rootScope, $http, ngProgressFactory) {
        var that = this;
        $rootScope.progrs = ngProgressFactory.createInstance();
        var progresstarted, progressbar = $rootScope.progrs;
        $rootScope.$watch(function() {
            var onlyJsonRequests = $http.pendingRequests.filter(function(r){
              return r.url.match(that.pattern);
            });
            return onlyJsonRequests.length;
        }, function(n) {
            if(n>0 && !progresstarted) {
                progresstarted = true; 
                progressbar.setColor(that.color);
               progressbar.setParent(document.getElementById(that.container)); 
                progressbar.start();
            } else if(n===0 && progresstarted) { 
                progressbar.complete(); 
                progresstarted = false;  
            }
        }) 
        return 'watching'
   };
});

Now we can set all the custom settings inside config section:

myApp.config(function(progressProvider) {
  progressProvider.setContainer('mainContainer');
  progressProvider.setPattern('json');
  progressProvider.setColor('blue');

Now inside our run section we can leave only progress injection:

myApp.run(function (progress) {
}) 

If you want to see the full code - look on this plnkr

12/14/16

Creating Material Chips Input For Angular2

What Are Those Chips I'm Talking About

Here are some of many implementations that can be found across the web:
materializecss
angularjs material
Look at this gif that demonstrates chips behavior:

Angular2 Chips

Recently I looked on Angular Material2 repository that being developed quickly those days. I noticed that currently the chips ui is not developed yet, So i decided to try to do it myself and here i want to share some of my thoughts about this challenge of mine...

References Of Experts

During my research i was helped reading by those great articles of those 3 great guys: implementing-angular2-forms-beyond-basics
linkup-custom-control-to-ngcontrol-ngmodel
understanding-controlvalueaccessor

First Way

We may make some component that gets chips array as two way binding parameter from its parent
HTML:


   //in parent component:
   values:string[]=['lolo']
    ...
   <chips [chips]="values"></chips>

chipsComponent.ts:

import {Component, Input, Output, EventEmitter} from '@angular/core'
@Component({
  selector: 'chips',
  template: `
   <div *ngIf="values">
      <span *ngFor="let value of values" style="font-size:14px"
          class="label label-default" (click)="removeValue(tag)">
        {{value}} <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
      </span>
      <span> | </span>
      <span style="display:inline-block;">
        <input [(ngModel)]="labelToAdd" style="width: 50px; font-size: 14px;" class="custom"/>
        <em class="glyphicon glyphicon-plus" aria-hidden="true" (click)="addValue(valueToAdd)"></em>
      </span>
    </div>
  `
})
export class Chips { 
  @Input()
  get chips() {
    return this.values;
  }
  set chips(val) {
    this.values = val;
    this.labelsChange.emit(this.values);
  }

  @Output()
  labelsChange: EventEmitter = new EventEmitter();

  removeValue(value:string) {
    var index = this.values.indexOf(value, 0);
    if (index != undefined) {
      this.values.splice(index, 1);
      this.labelsChange.emit(this.values);
    }
  }

  addValue(value:string) {
    this.values.push(this.labelToAdd);
    this.labelsChange.emit(this.values);
    this.labelToAdd = '';
  }
}

see this code runs in plunker

Second Way (using Angular2 Forms)

My goal was to create a component/driective that will use ngModel directive to update the model:



 <material-chips [(ngModel)]="tags" ></material-chips>


For this we need to implement valueAccessor interface:

import {Component, NgModel, NgModule, OnInit, Input, Output, EventEmitter, ElementRef, forwardRef} from '@angular/core'

import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';


const noop = () => {
};

export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => Chips),
    multi: true
};

@Component({
  selector: 'chips',
  template: `
    <div *ngIf="values">
      <span *ngFor="let value of values" style="font-size:14px"
          class="label label-default" (click)="removeValue(tag)">
        {{value}} <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
      </span>
      <span> | </span>
      <span style="display:inline-block;">
        <input [(ngModel)]="labelToAdd" style="width: 50px; font-size: 14px;" class="custom"/>
        <em class="glyphicon glyphicon-plus" aria-hidden="true" (click)="addValue(valueToAdd)"></em>
      </span>
    </div>
  `,
   providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR] 
})
export class Chips  implements ControlValueAccessor { 
  //by the Control Value Accessor
  private onTouchedCallback: () => void = noop;
  private onChangeCallback: (_: any) => void = noop;
  registerOnChange(fn: any) { this.onChangeCallback = fn;}
  registerOnTouched(fn: any) { this.onTouchedCallback = fn;}

  @Output()
  labelsChange: EventEmitter = new EventEmitter();

  removeValue(value:string) {
    var index = this.values.indexOf(value, 0);
    if (index != undefined) {
      this.values.splice(index, 1);
      this.labelsChange.emit(this.values);
    }
  }

  addValue(value:string) {
    if(!this.labelToAdd || this.labelToAdd.trim()===''){return;}
    this.values.push(this.labelToAdd);
    this.labelsChange.emit(this.values);
    this.labelToAdd = '';
  }
  
  //From ControlValueAccessor interface
  writeValue(value: any) {
      if (value !== this.values) {
          this.values = value;
      }
  } 

}


12/3/16

Flex Box And Prejudice

I don't know why some people have some superstitious feelings about using flex box css property. In this article I will try to convince you that using flex will make your life(as html programmer) much easier.
First of all i must recommend this great article that also supplies this great playground
For getting things easy to understand - I will start straight with some example:
lets say you need to build a page with following layout:
You have 2 groups of buttons - the one group should stick to the left and other one - should stick to the right. I want to show you two different ways to implement this layout:
HTML:


    
    <nav>
       <div class="left-menu">
          <button class="fa fa-refresh"></button>
          <button>Provisioning Events</button>
        </div>
        
       <div class="right-menu">
          <button>butt1</button>
          <button>butt2</button>
          <button>butt3</button>          
        </div>>         
    </nav>

CSS
1. using the "justify-content:space-between" css feature:

nav{
   display:flex; 
   justify-content:space-between;
}

2. using "flex:1" rule on style of .right-menu

nav{
   display:flex; 
}
.right-menu{
  flex:1;
  display:flex; 
  justify-content:flex-end;
}

What is "flex:1"?

"flex:1" shorthand for the flex-grow, flex-shrink and flex-basis properties, in our case means that .right-menu should capture all available space at the right of .left-menu.
Hope now you can see that flex-box feature has more various options to play with (more flexible after its name)...

One More Example

How to make footer to stick to bottom of the parent element? Lets say you have some kind of dialog with content and footer (which suppose to stick to the floor), and content need to "catch" all the remaining space?


   <div class="modal">
       <form>
         <main>
           content content content
           <br/>
           
           <div style="display:none;color:red" id="koko">
              something different here...
           </div>
         </main>
         <footer> 
           <button>footer</button>
         </footer>
       </form>
   </div>

So, Flex-Box can be helpful again:

.modal form{
  display:flex;
  flex-direction:column;
  height:230px;
  width:240px; 
  background:red;
  color:#fff;
}
main{  
  background:blue;
  flex:1;
}
#koko{
  height:170px;
  background:#fff;
}
footer{
  padding:5px;
}


JS Bin on jsbin.com

Getting started with docker

It is very simple to get started usig docker. All you need to do-is download the docker desktop for your system Once you get docker syste...