1/23/16

creating chart component - angular2

After creating my first component which displays current time, i want to try something little bit complicate.
This time lets create a component which displays chart:

For draw a chart i will use jquery flot library which is one of libraries/plugins which let you to create beautiful charts.
According to jquery flot docs - for draw a chart you need to pass html element(selector), data and options to plot plugin, like this:

$.plot( selector, dataset, options);


Component

As in previous case, lets create component

import {Component, ElementRef} from 'angular2/core';

@Component({
  selector: 'flot',
  template: `<div>loading</div>`

})

export class FlotCmp {
  private dataset;
  private options;
  private width = '100%';
  private height = 220;

  
  constructor(public el: ElementRef) {
        this.dataset = [{label: "line1",data:  [[1, 130], [2, 40], [3, 80], [4, 160], [5, 159], [6, 370], [7, 330], [8, 350], [9, 370], [10, 400], [11, 330], [12, 350]]}];
        this.options = {
            series: {
                lines: { show: true },
                points: {
                    radius: 3,
                    show: true
                }
            }
        };
        
        let plotArea = $(this.el.nativeElement).find('div');
        plotArea.css({
            width: this.width,
            height: this.height
        });
        $.plot( plotArea, this.dataset, this.options);

  }//end of constructor
}

Yes!!! Now the chart s created!!!
Note that for access the html element on which i want to apply the chart, i'v used ElementRef module

Passing properties

Our next goal is to make newly created component configurable - e.g. ability to pass dataset, options, width, height configuration properties through the attributes:
  
     <flot [options]="splineOptions" [dataset]="dataset" height="550px" width="100%"></flot>
 
"Piece of cake!" you may say, like in previous case use the "input" factory and you done:

import {Component, ElementRef, Input} from 'angular2/core';

@Component({
  selector: 'flot',
  template: `<div>loading</div>`

})
//this will cause error!!!
export class FlotCmp{

  private width = '100%';
  private height = 220;
  static chosenInitialized = false;
  
  @Input() private  options: any;
  @Input() private  dataset:any;
  @Input() private  width:string;
  @Input() private  height:string;
      
   
  constructor(public el: ElementRef) {
        plotArea.css({
            width: this.width, 
            height: this.height
        });
        $.plot( plotArea, this.dataset, this.options);        
  }
  ...  

Bad idea! No chart created anymore.
But why? Because the constructor runs before input setters passing their values. We must move plot initiating logic to some later phase. I find the solution here. This guy uses AfterViewInit factory:

import {Component, ElementRef, Input, AfterViewInit} from 'angular2/core';

@Component({
  selector: 'flot',
  template: `<div>loading</div>`

})

export class FlotCmp  implements AfterViewInit{

  private width = '100%';
  private height = 220;
  static chosenInitialized = false;
  
  @Input() private  options: any;
  @Input() private  dataset:any;
  @Input() private  width:string;
  @Input() private  height:string;
 
  constructor(public el: ElementRef) {}

  ngAfterViewInit() {
      if(!FlotCmp.chosenInitialized) {
        let plotArea = $(this.el.nativeElement).find('div').empty();
        plotArea.css({
            width: this.width, 
            height: this.height
        });
        $.plot( plotArea, this.dataset, this.options);    
        FlotCmp.chosenInitialized = true;
      }
  } 
} 


Now the chart initiating logic is in the ngAfterViewInit method which activates after properies already set.
Hope you have fun reading!
More posts about angular2 stuff (used for me as inspiration source)

1/13/16

Building my first directive with angular2

Recently i started to play with recently released beta of angular2.
I'm totally beginner and i want to build very simple thing.
I want to build the component (component is like directive in angular 1.) that displays current time in format given as a parameter (through the attribute format).
  
  
    <now format="'h:mm:ss'"></now>
  
When rendered HTML, should look like this:

How to run angular2?

First thing you need then you want to run angular2 is environment.
You can use one of angular2 starter kits like this one Or just open plunker and select "Editor" -> "New" -> "AngularJs" -> "2.0.x TS" and viola!! you are angular2 programmer!


Component

The first basic thing in angular2 is component, so: Lets create a component:


import {Component} from 'angular2/core'

@Component({
  selector: 'now',
  template: `

{{date}}

` }) export class Now { private date; constructor() { this.date = new Date(); } }

Yoo hoo!!! The component created and running!!!
And it displays the current date!!!
But one little disturbing thing is that date appears raw , which is little bit ugly...

So lets improve the component by formatting the output.


Pipe (Filter)

Like in sngular 1. there are filters in angular2, they called pipes


import {Component} from 'angular2/core'

@Component({
  selector: 'now',
  template: `

{{date | date :'dd/MM/yyyy'}}

` })

Getting value from attribute (The tricky part)

As we already said the desired format should be passed through the attribute. But how to access this attribute from inside component constructor? Fortunately there is Attribute module which enables you to inject attribute into constructor parameters:

import {Component, Attribute} from 'angular2/core'
export class Now {
   private date;
   
  constructor(@Attribute("format") format) { 
    this.format = format;
    this.date =  new Date(); 

  } 

} 

Better way

After Lenin's older brother was executed because he tried(but failed) to kill king of Russia with bomb, young Lenin said "We will go different way"...
After looking at angular2 docs i found better (more angular2mish) way which says that if we want to pass attribute to component we must use square brackets :

  
  
    <now [format]="'h:mm:ss'"></now>
  

I will use @Input module instead of @attribute




import {Component,  Input} from 'angular2/core'

@Component({
  selector: 'now',
  template: `
      

{{date | date: _format}}

` }) export class Now { private date; @Input() set format(formatName:string){ this._format = formatName; } constructor() { this.date = new Date(); } }

How to update time each second?

Little nice thing to add here is ability to update the time displayed in directive each second. For achieve this i'm using ES6 fat arrow syntax


export class Now {
   private date;
   @Input() set format(formatName:string){
     this._format = formatName;
   
   }   
  constructor() { 
    this.date =  new Date(); 
    
    setInterval(() => {
        this.date =  new Date();
     }, 1000);
  } 

} 


View it on plunker:

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...