Posts on this Category



Creating an Angular2 Image Gallery

In order to make this tutorial easier for beginners I’m going to start by creating the simplest possible gallery, from there I’m going to develop and add more functionalities to it, which will increasingly make the gallery more complex as we proceed. If you are already familiar and have some experience with angular2 this entire tutorial will be easy for you, but if you’re a beginner it’s really important that you understand every detail from one step before you move on to the next, with that in mind let’s get started!

The first step, of course, is to create an angular2 project, if you don’t know how to create one just follow the instructions from the Angular2 Quickstart.

Before we begin let’s add the bootstrap and jquery scripts to our project, we’re going to need them later, just copy/paste the following code to your index.html.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js" ></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" ></link>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" ></link>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" ></script>

Now we can start working on the gallery component, as I said before let’s focus on the basics first, for now all we need is a gallery that shows a list of thumbnails and a dialog with the selected image. This is how it should look like in code:

gallery.component.ts

import {Component, Input} from '@angular/core';
 
@Component({
  selector: 'gallery',
  template: `
	<div class="modal fade" id="selectedImageModal" >
	  <div class="modal-dialog" role="document">
	    <div class="modal-content">
	      <div class="modal-body">
	         <img *ngIf="selectedImage" src="{{selectedImage.url}}" >
	      </div>
	    </div>
	  </div>
	</div>
  	<ul id="thumbnailsList">
  	   <li *ngFor="let image of datasource" >
  	      <img src="{{image.url}}" class="tn"
  		  width="191" height="146"  
  		  data-toggle="modal" data-target="#selectedImageModal"
                  (click)=setSelectedImage(image)>
  	   </li>
  	</ul>
  `,
  styles: [`
  	ul { padding:0; width:780px; margin:20px auto}
  	li { display:inline;}
        .tn{ 
	   margin:2px 0px;
	   box-shadow:#999 1px 1px 3px 1px; 
	   cursor: pointer 
        }
  	.modal-content {
	    width: 670px !important;
	}
  `]
})
export class GalleryComponent { 
 
   @Input() datasource;
   selectedImage;
 
   setSelectedImage(image){
      this.selectedImage= image;	
   }
}

Look how simple the template is, we have just two elements: the selectedImageModal and the thumbnailsList. The first one is a Bootstrap dialog with the selected image and the second is the list of thumbnails.

In the GalleryComponent class we have a variable called datasource that provides everything we need to render the component, it is an array of objects containing all the data regarding each image (url, caption, title, etc), all we have to do is to iterate over this dasaset creating an img element for each object on the array, the result will be our thumbnails list.

A really important detail is that the variable datasource is decorated with @Input(), which means that it must be passed to our component as an attribute (I’m going to show how to do that in a moment), this will allow us to reuse the component to show different sets of images across the application.

We also have the selectedImage variable, as the name suggests this variable holds the object with the selected image properties. To select an image the user must click on its thumbnail, when the click occurs the method setCurrentImage will be called thanks to the (click)=setSelectedImage(image) we’ve put on the thumbnails, then a bootstrap dialog will pop up showing the full-sized selected image.

Lastly, I had to do some styling to make this component look like a gallery, one way to use CSS in an angular2 component is to just add the attribute styles to the @Component decorator like I did in this example.

Now we already have a basic gallery, let’s see how we can use it:

app.component.ts

import {Component } from '@angular/core';
 
@Component({
  selector: 'my-app',
  template: `
    <gallery [datasource]=images></gallery>
  `,
})
export class AppComponent { 
   images;
 
   constructor(){
      this.images = [
	{"url":"http://your_image1_url"},
	{"url":"http://your_image2_url"},
	{"url":"http://your_image3_url"},
	{"url":"http://your_image4_url"},
	{"url":"http://your_image5_url"},
	{"url":"http://your_image6_url"},
	{"url":"http://your_image7_url"},
	{"url":"http://your_image8_url"},
	{"url":"http://your_image9_url"},
	{"url":"http://your_image10_url"},
	{"url":"http://your_image11_url"},
	{"url":"http://your_image12_url"}
      ];
   }
}

The usage is very simple, the only thing we have to be concerned here is to pass a datasource to the gallery, in this class I have the images variable that will serve as a datasource, I’m passing it by adding the [datasource]=images to the gallery element on the template.

This is the result so far:

Angular2 Image Gallery - Thumbnails
Angular2 Image Gallery – Thumbnails
Angular2 Image Gallery – Selected Image
Angular2 Image Gallery – Selected Image

Adding the Title and Caption

As I just explained, we have to pass to the gallery component an array of objects containing all the data regarding the images, in our case the variable images from the app.component.ts is our datasource, let’s take a closer look at one of the objects that composes it:

{"url":"http://your_image1_url"}

Since the url is the only property we’ve used so far, it’s the only attribute in the object. To be able to show the title and caption we have to modify the datasource by adding these two properties to the objects, this is how it should look like after the modification:

{
  "url":"http://your_image1_url",
  "title":"Aliquam erat volutpat",
  "caption":"imperdiet imperdiet. Nullam ut ligula vitae arcu vulputate dictum ut quis elit."
}

Now we can use these new attributes on the gallery.component.ts, when a user clicks on the thumbnail we’re currently showing the selected image with this img element:

<img *ngIf="selectedImage" src="{{selectedImage.url}}" >

Let’s replace the img with a div that contains, besides the image, also the title and caption:

<div class="selectedImage" *ngIf="selectedImage">
   <img src="{{selectedImage.url}}" >
   <div class="caption">
      <p><strong>{{selectedImage.title}}</strong></p>
      <p>{{selectedImage.caption}}</p>
   </div>
</div>

And once again we have to add some styles to the component:

.selectedImage{ 
	width:640px;
	position:relative }
.caption{
	position:absolute;
        height:70px;
	width:100%;
	top:410;
	left:0;
	opacity:0.9;
	background-color:black;
	color:white;
	padding:5px;
	font-family:verdana;
	font-size:12px;
}
p {
   -webkit-margin-before: 5px !important;
   -webkit-margin-after: 5px !important;
}

This is the result:

Image Title and Caption
Image Title and Caption

Adding the Navigation Arrows

After running your application you should’ve noticed that when you select an image there’s no way to select another without closing the dialog first, we can make things much easier for the user by adding navigation arrows, for that to be possible we have to modify the template again by adding two new divs above the caption:

<div class="selectedImage" *ngIf="selectedImage">
   <img src="{{selectedImage.url}}" >
   <div class="arrow-back" (click)=navigate(false)>
      &lt;
   </div>
   <div class="arrow-forward" (click)=navigate(true)>
      &gt;
   </div>
   <div class="caption">
      <p><strong>{{selectedImage.title}}</strong></p>
      <p>{{selectedImage.caption}}</p>
   </div>
</div>

The new divs will serve as the navigation arrows, notice that they are calling the function navigate, that’s the function responsible for changing the selected image, let’s see how it works:

navigate(forward){
   var index = this.datasource.indexOf(this.selectedImage)+(forward ? 1: -1);
   if(index >= 0 && index < this.datasource.length){
      this.selectedImage = this.datasource[index];	
   }
}

The function receives a boolean as parameter, its value will be false if we click on back and true if we click on the forward arrow. To be able to change the selected image we first have to find out its index, we can easily do that by using indexOf, then we add/subtract 1 from this value and we already have a new index, now we can use this index to get the next/previous image from the datasource and assign it to the selectedImage variable.

Lastly, let’s take care of the styles:

.btn-back, .btn-forward{
	position:absolute;
	opacity:0.9;
	background-color:black;
	padding:10px;
	top:190;
	color:white;
	text-weight:bold;
	cursor:pointer;
}
 
.btn-forward{
	left:612;
}

This is the result:

Navigation Arrows
Navigation Arrows

Adding Keyboard Shortcuts

I’m not going to go into details about this because I’ve already written a post about keyboard shortcuts, you basically have to add the element host to your component:

host: {'(window:keydown)': 'hotkeys($event)'}

This allows us to call a function on the keydown event, in this case I’m calling the function hotkeys:

hotkeys(event){
   if(this.selectedImage){
      if (event.keyCode == 37){
         this.navigate(false);
      }else if(event.keyCode == 39){
         this.navigate(true);
      }
   }
}

In this function I’m just checking the keycode and taking actions accordingly, if the user presses the left arrow (keycode 37) I’m calling navigate(false) and if he presses the right arrow (keycode 38) I’m calling navigate(true).

That’s it guys! I’m going to leave it like that for now, if there are other functionalities you want to add please leave a comment, all suggestions are welcome!

Angular 2 Tutorial: Adding HotKeys (Keyboard shortcuts) to a Component

Arguably hotkeys can substantially increase the usability of an application, the less the users have to touch the mouse the better will be their experience with the application.

Luckily for us there is a very easy way of defining hotkeys on angular2, which is by adding a listener to the host component, we can accomplish this by just adding the element host to the @Component decorator.

Let’s take a look at an example:

import {Component } from '@angular/core';
 
@Component({
  selector: 'hotkeys-app',
  host: {'(window:keydown)': 'hotkeys($event)'},
  template: `
  	<button (click)=showMessage()>Hotkey Test</button>
  `,
})
export class AppComponent { 
 
   hotkeys(event){
      if (event.keyCode == 65){
         this.showMessage();
      }
   }
 
   showMessage(){
      alert('Hotkey Test');
   }
}

As you can see I’ve used the element host to add a listener to the window:keydown event, it will call the function hotkeys(event) every time this event occurs, all we have to do now on this function is to determine which key was pressed and take actions accordingly.

As an example I’ve placed a button on the template, let’s suppose we want the action of this button, which is the showMessage() funtion, to execute when the user presses the letter 'a' on the keyboard. On the hotkeys function we have the event parameter containing the keyCode, we have to check this value to see which key was pressed, in this case I’m calling showMessage() when the keycode is 65 (which is code for the letter 'a').

It’s also very common to use combinations as hotkeys, like for example ctrl+a. To do that we just have to change our condition a little bit:

if (event.keyCode == 65 && event.ctrlKey){

The only diference is that besides checking the keyCode I’m also using the event.ctrlKey to check if the ctrl key is pressed.

That’s it guys! Just leave a comment if you have any doubts.

Angular2 Forms Tutorial: Creating Custom Validators

Every now and then developers come across situations where existing validators are not suitable for their needs, if you are facing this situation your best option is to create a custom validatior, to illustrate how you can do that in angular2 I’m going to create a simple custom validator that will verify if the field value starts with a given string, it’ll be something like this:

<input type="text" startWith="ABC" ...>

In this example the attribute startWith is my validator, for this input to be valid it must contain a value that starts with ABC.

Now let’s see how it works, a custom validator is nothing more than a attribute directive that implements the Validator class, before we proceed to the details let’s take a look at the code:

import { Directive, Input } from '@angular/core';
import { NG_VALIDATORS, Validator, AbstractControl } from '@angular/forms';
 
@Directive({ 
  selector: '[startWith]',
  providers: [{provide: NG_VALIDATORS, useExisting: CustomValidatorDirective, multi: true}] 
})
export class CustomValidatorDirective implements Validator{
  @Input('startWith') expr: string;
 
  validate(control: AbstractControl) {
    if(control.value && !control.value.startsWith(this.expr)){
        return {'startWith': control.value};
    }
    return null;
  }
}

Every validator has a validate() method, angular2 will call it every time the application needs to validate the field, note that it receives an AbstractControl as a parameter, which is the form control itself, this parameter will give us access to all of the field attributes, including the value (the only one we’re going to use in this tutorial). Also note that I’ve declared an @Input, this is how I’m getting the value "ABC" passed to the directive in the example above.

Now that we have the field value and the input we can implement the validate method and check if the field value contains the expression. If the field is valid the function returns null, otherwise it returns the validation error object.

Lastly, before you can use the validator, you have to register it in the app.modules.ts:

...
import { CustomValidatorDirective } from './customValidator.directive';
 
@NgModule({
  declarations: [ ... ,CustomValidatorDirective],
  ...
})
export class AppModule { }

Angular2 Tutorial: Creating Attribute Directives

According to Angular2 documentation, directives are classes that can change the component behavior or/and appearance, which basically means they can add CSS classes and styles, register events and manipulate the component’s properties.

In this tutorial I’m going to show you how to create a very simple directive that will register the click event and add a CSS style to the component. I know we can do this without directives, but keep in mind that this is just an example I’m using to illustrate how directives work.

So let’s jump right into the code:

message.directive.ts

import { Directive, ElementRef, Input, Renderer } from '@angular/core';
 
@Directive({ selector: '[showMessage]' })
export class MessageDirective {
 
    constructor(el: ElementRef, renderer: Renderer) {
       renderer.setElementStyle(el.nativeElement, 'cursor', 'pointer');
       renderer.listen(el.nativeElement, 'click', function(){
         alert('Test');
       });
    }
}

As you can see, a directive is just a regular class decorated with @Directive, this decorator allows you to specify a selector, which is the name you’re going to use to call your directive later, in this example the selector is showMessage.

Now let’s take a look at the constructor, to make things easier angular2 is injecting two objects for us: ElementRef and Renderer. The first one allows us to access the DOM element, as the second is used to add/modify its properties.

There are two things I’m doing in this constructor, in the first line I’m using the Renderer’s setElementStyle function to change the cursor style to pointer, and in the second I’m just registering a callback function to the click event.

To make our directive work we also have to declare it in the app.module.ts:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }   from './app.component';
import { FormsModule }   from '@angular/forms';
import { MessageDirective } from './message.directive';
 
@NgModule({
  imports:      [ BrowserModule, FormsModule],
  declarations: [ AppComponent, MessageDirective],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

That’s it, easy right! Now we can use the directive by just adding its selector to the component as follows:

<p showMessage>Click Here</p>

If you run your application you’ll see that this p element looks like a link, when you click on it the message 'Test' pops up.

Angular2 Forms Tutorial: Validating Required Fields

Angular2 Form Validation
Angular2 Form Validation

In this tutorial I’ll give you a simple example of how to validate a form with angular2. As you can see in the image, the example consists of a form with two required fields, the form can only be submitted if both fields are valid.

I’m going to use bootstrap for styling, if you want your form to look like the image above you just have to add the follwoing scripts to your index.html:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" >
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" >
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" ></script>

Now let’s take a look at our component:

import {Component} from '@angular/core';
 
@Component({
  selector: 'form-validation-example',
  template: `
     <form (ngSubmit)="submit()" >
	<div class="form-group has-feedback" 
	     [ngClass]="{ 'has-error' : !firstNameControl.valid && submitAttempt }">
           <label class="control-label" >First Name</label>
           <input type="text" class="form-control"
	      name="firstName" [(ngModel)]="firstName" #firstNameControl="ngModel" required>
           <span *ngIf="!firstNameControl.valid && submitAttempt"
	      class="glyphicon glyphicon-remove form-control-feedback" ></span>
	</div>
	<div class="form-group has-feedback" 
	     [ngClass]="{ 'has-error' : !emailControl.valid && submitAttempt }">
	   <label class="control-label">E-mail</label>
	   <input type="text" class="form-control"
              name="email" [(ngModel)]="email" #emailControl="ngModel" required>
           <span *ngIf="!emailControl.valid && submitAttempt"
	      class="glyphicon glyphicon-remove form-control-feedback" ></span>
	</div>
	<button type="submit" class="btn btn-default" (click)=initSubmit()>Submit</button>
     </form>
  `
})
export class FormComponent {
      submitAttempt = false;
 
      initSubmit(){
	  this.submitAttempt = true;
      }
 
      submit(){
 	  console.log('success!');
      }
}

This is just a regular form, what makes the fields required is the required attribute at the end of each input, just using this attribute will already be enough to prevent the form from submitting, but it won’t change the field style as shown in the demo at the beginning.

To be able to change the style of the input we first have to know if the field is valid or not, an easy way to achieve this is to declare a template reference variable for each field, if you take a look at the code you’ll see the attribute #firstNameControl="ngModel" on the first input and #emailControl="ngModel" on the second, that’s how template reference variables are declared. Now I can use the names firstNameControl and emailControl to access properties of my inputs on other parts of my template, but the only one that matters to us is the property valid.

We also need a way to determine if the submit button was clicked or not, that’s why I’ve created the variable submitAttempt, it’s false by default but it’ll be set to true once the button is clicked.

By using the template reference variables and the submitAttempt variable we can now write the condition that changes the styles, which is !firstNameControl.valid && submitAttempt for the first field and !emailControl.valid && submitAttempt for the second. These conditions are used to add the bootstrap class has-error on each form-group and also to render the icon at the end of the input.

Lastly we have the submit() function which will just print the string ‘success!’ on the console, this function will only be called if both fields are valid.

Interacting with Child Components in Angular2

There are lots of situations where we have to divide a component into several sub-components, resulting in a parent with N child components that somehow have to interact with the parent, like for example a menu component like this:

<menu-component>
   <menu-item [label]="'Item 1'"></menu-item>
   <menu-item [label]="'Item 2'"></menu-item>
   <menu-item [label]="'Item 3'"></menu-item>
   <menu-item [label]="'Item 4'"></menu-item>
   <menu-item [label]="'Item 5'"></menu-item>
</menu-component>

In this case the menu-component class must have access to every menu-item in order to completely render the component, that’s what I’m going to show you in this tutorial, but before we begin keep in mind that this is not a real menu component, it’s just an example I’m using to demonstrate how the components can interact.

Now let’s see how it works, here are the sources of both components:

MenuItemComponent

@Component({
  selector: 'menu-item',
  template: ``,
})
export class MenuItemComponent {
  @Input() label;
 
  constructor(menu: MenuComponent) {
    menu.items.push(this);
  }
}

MenuComponent

@Component({
  selector: 'menu-component',
  template: `
      <ul>
         <li *ngFor="let item of items">{{item.label}}</li>
      </ul>
  `
})
export class MenuComponent { 
  items: MenuItemComponent[] = [];
}

The parent iterates over a list of menu items in the template in order to display the label of each one of them in a li element, but as you can see the items array is empty and I’m not adding anything to it in this class, now if you take a look at the MenuItemComponent‘s constructor you’ll see that Angular2 makes things very easy for us by injecting the parent component, allowing each item to access the array in the parent and add itself to it.

That’s pretty much it guys, this was a very short tutorial but I hope it was helpful for you, just leave a comment if you have any doubts.

Creating an Angular2 Datatable from Scratch PART 2: Filtering the Data

Continuing from where we stopped at Part 1, today we’re going to add the filter functionality to the table, but before we start let’s do some styling. I’m going to use Bootstrap, but if you don’t want you don’t have to, feel free to style your component as you like. But if you decide to use Bootstrap as well you’ll have to add these scripts to your index.html:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" >
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" >
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" ></script>

Now I’m going to add the class table to the table element in the DatatableComponent, this class will make the grid look like this:

Table With Bootstrap Style
Table With Bootstrap Style

It looks so much better already! Now let’s get started with the filter, most of the modifications will be made on the datatable.component.ts file, here’s the component after the changes:

import {Http, Response} from '@angular/http';
import {Injectable, Component, Input} from '@angular/core';
import {ColumnComponent} from './column.component';
 
@Component({
  selector: 'datatable',
  template: `
      <input type="text" class="form-control" *ngIf=enableFilter [(ngModel)]=query 
         (keyup)=filter() placeholder="Filter" />
      <table class="table">
        <thead>
          <tr>
            <th *ngFor="let column of columns">{{column.header}}</th>
          </tr>
        </thead>
        <tbody *ngFor="let row of getData()">
	  <tr>
	    <td *ngFor="let column of columns">{{row[column.value]}}</td>
	  </tr>
        </tbody>
      </table>
  `
})
export class DatatableComponent { 
 
  @Input() dataset;
  @Input() enableFilter = false;
  columns: ColumnComponent[] = [];
  query = "";
  filteredList;
 
  addColumn(column){
    this.columns.push(column);
  }
 
  getData(){
    if(this.query !== ""){
      return this.filteredList;
    }else{
      return this.dataset;  
    }
  }
 
  filter(){
    this.filteredList = this.dataset.filter(function(el){
      var result="";
        for(var key in el){
          result+= el[key];
        }
        return result.toLowerCase().indexOf(this.query.toLowerCase()) > -1;
    }.bind(this));
  }
}

Let’s start by talking about the new attributes:

enableFilter: This is an input that indicates weather the filter is going to be enabled or not, it’s false by default.
query: Variable that stores the filter typed by the user.
filteredList: This variable is going to store the new dataset after the filtering, it’s necessary to use a different array in order to preserve the original data.

Now the new functions:

filter(): Function responsible for filtering the data when the user types something on the input, it’ll filter the data from the dataset variable and assign the result to the filteredList.
getData(): Our table will work simultaneously with two arrays, the dataset and filteredList, this function is responsible for telling which one will be used at any given moment, if the table has filtered data to show it’ll use the filteredList otherwise it’ll use the dataset.

Besides the new attributes and functions I’ve also modified the template a little bit, in the tbody I’ve change the ngFor from let row of dataset to let row of getData(), and as you can see there is an input above the table where the user can type, it’ll call the filter() function on the keyup event and it’ll only be visible when the enableFilter is true (For this input to work we also have to import the FormsModule on the app.module.js).

Now your datatable can be used like this:

<datatable [dataset]=cities [enableFilter]=true >
      <column [value]="'id'" [header]="'Id'"></column>
      <column [value]="'city'" [header]="'City'"></column>
      <column [value]="'country'" [header]="'Country'"></column>
 </datatable>

The only thing that has changed is that now we have the option enableFilter that will render an input above the table when set to true.

Creating an Angular2 Datatable from Scratch

Some time ago I’ve posted a tutorial on how to create a datatable with ag-grid, it didn’t take long before people start complaining that ag-grid wasn’t working the way I described in the tutorial, that’s because angular2 is changing rapidly rendering the component and/or the tutorial obsolete.

Today I’m going to show you again how to create a datatable, but this time I’m going to do it without ag-grid or any other third-party component, this is how our component will look like after we’re done:

<datatable [dataset]=cities>
    <column [value]="'id'" [header]="'Id'"></column>
    <column [value]="'city'" [header]="'City'"></column>
    <column [value]="'country'" [header]="'Country'"></column>
</datatable>

That’s the simplest datatable structure I could come up with, as you can see we’re going to create two components: datatable and column.

Let’s take a look at the column component first:

import {Component, Input} from '@angular/core';
import {DatatableComponent} from './datatable.component';
 
@Component({
  selector: 'column',
  template: ``,
 
})
export class ColumnComponent {
	@Input() value;
	@Input() header;
 
	constructor(table: DatatableComponent) {
    	   table.addColumn(this)
  	}
}

This component has two attributes as inputs: value and header.

Value: This is the name of the attribute from your JSON dataset that will be displayed on this column (I’m going to talk about the dataset in a minute).
Header: As the name suggests, this is the column header text.

Besides these two attributes, there’s also the constructor, which very conveniently injects the DatatableComponent, allowing us to add this column to an array from the parent component. To fully understand why I’m doing this we have to take a look at the DatatableComponent:

import {Http, Response} from '@angular/http';
import {Injectable, Component, Input} from '@angular/core';
import {ColumnComponent} from './column.component';
 
@Component({
  selector: 'datatable',
  template: `<table>
               <thead>
                 <tr>
                   <th *ngFor="let column of columns">{{column.header}}</th>
                 </tr>
               </thead>
	       <tbody *ngFor="let row of dataset">
	  	 <tr>
	  	   <td *ngFor="let column of columns">{{row[column.value]}}</td>
	         </tr>
	       </tbody>
  	     </table>
  `
})
export class DatatableComponent { 
 
  @Input() dataset;
  columns: ColumnComponent[] = [];
 
  addColumn(column){
    this.columns.push(column);
  }
}

In this component we have the attribute dataset as an input (which will receive the JSON dataset) and the array of columns I just mentioned, each column will add itself to this array as we’ve seen on the ColumnComponent‘s constructor. In the template I’m iterating over both the dataset (rows) and the columns to create a regular HTML table.

After creating these two components we can use the datatable as I showed in the beginning, here is the app.component.ts:

import {Http, Response} from '@angular/http';
import {Injectable, Component } from '@angular/core';
 
@Component({
  selector: 'my-app',
  template: `<datatable [dataset]=cities>
                  <column [value]="'id'" [header]="'Id'"></column>
                  <column [value]="'city'" [header]="'City'"></column>
                  <column [value]="'country'" [header]="'Country'"></column>
             </datatable>
             `,
 
})
export class AppComponent { 
    cities;
 
    constructor(private http:Http) {
        this.http.get('data/cities.json')
                .subscribe(res => this.cities = res.json());
    }
}

Note that in the constructor I’m loading my dataset from the file cities.json, for more datails about that click here.

We’re almost done, the last thing we have to do is to declare our components in the app.module.ts:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule }      from '@angular/http';
import { AppComponent }   from './app.component';
import {DatatableComponent} from './datatable.component';
import {ColumnComponent} from './column.component';
 
@NgModule({
  imports:      [ BrowserModule, HttpModule ],
  declarations: [ AppComponent,DatatableComponent, ColumnComponent],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

That’s it for now guys! Click here to see the part 2 of this tutorial where I’m showing how to add the filter functionality, if you need other specific features please let me know in the comments, any suggestions are welcome!

Passing Parameters to an Angular2 Component

One of the greatest advantages of using components is reusability, which means once you’ve create your component you can use it in several places across your project without having to recreate it everytime. But for that to be possible we have to be able to pass parameters to our components, that’s what I’ll be showing you in this tutorial.

Some time ago I’ve written a tutorial on how to create an autocomplete, but I didn’t show how to pass the data as a parameter, it was hardcoded in the component, so if I had to use it somewhere else with other data I would have to rewrite everything. Of course nobody wants that, so let’s see how we can make it better.

This is the component we have so far (I’ve omitted some code to make it easier to read):

import {Component, ElementRef, Input} from 'angular2/core';
 
@Component({
    selector: 'autocomplete',
    template: `
        //template here
    	`
})
export class AutocompleteComponent {
    public countries = [ "Albania","Andorra","Armenia","Austria","Azerbaijan","Belarus","Belgium","Bosnia & Herzegovina",
                        "Bulgaria","Croatia","Cyprus","Czech Republic","Denmark","Estonia","Finland","France","Georgia",
                        "Germany","Greece","Hungary","Iceland","Ireland","Italy","Kosovo","Latvia","Liechtenstein",
                        "Lithuania","Luxembourg","Macedonia","Malta","Moldova","Monaco","Montenegro","Netherlands",
                        "Norway","Poland","Portugal","Romania","Russia","San Marino","Serbia","Slovakia",
                        "Slovenia","Spain","Sweden","Switzerland","Turkey","Ukraine","United Kingdom","Vatican City"];
    ...
}

What we have to do here is to remove this array of countries and replace it with a variable annotated with the @Input decorator from angular2/core. After the modification the component should look like this:

export class AutocompleteComponent {
    @Input() data;
    ...
}

The @Input() decorator makes the data variable a data-bound property, now this variable can receive data passed from a parent component.

Now let’s create a parent component that uses our autocomplete:

import {Component} from 'angular2/core';
import {AutocompleteComponent} from './autocomplete.component';
 
@Component({
    selector: 'my-app',
    directives:[AutocompleteComponent]
    template: `
            <autocomplete [data]=countries ></autocomplete>
    	`
})
export class AppComponent {
    public countries = [ "Albania","Andorra","Armenia","Austria","Azerbaijan","Belarus","Belgium","Bosnia & Herzegovina",
                        "Bulgaria","Croatia","Cyprus","Czech Republic","Denmark","Estonia","Finland","France","Georgia",
                        "Germany","Greece","Hungary","Iceland","Ireland","Italy","Kosovo","Latvia","Liechtenstein",
                        "Lithuania","Luxembourg","Macedonia","Malta","Moldova","Monaco","Montenegro","Netherlands",
                        "Norway","Poland","Portugal","Romania","Russia","San Marino","Serbia","Slovakia",
                        "Slovenia","Spain","Sweden","Switzerland","Turkey","Ukraine","United Kingdom","Vatican City"];
 
}

As you can see, I’ve just copied the data from the other component to this one. If you take a look at the autocomplete in the template you’ll see that it has the attribute [data]=countries, this is how I’m assigning the countries list to that variable with the @Input decorator I’ve create before. If you run your project you’ll see that it’s working the same way as before, but now you can create more autocompletes passing different datasets.

Hope this tutorial was helpful, just leave a comment if you have any doubts.

Integrating an Angular2 app with a PHP app

In this tutorial I’m going to show you how to use Angular2 Http client to communicate with an php application. I don’t want this to be a very long post, so I’m going to make everything as simple as possible.

The first step, of course, is to provide a php web service, it doesn’t need to be anything sophisticated, just returning a json dataset will do for now. We can achieve this by creating an php app with just an index.php file containing the following code:

<?php
 	header("Access-Control-Allow-Origin: *");
	$data = array(
		array('id' => '1','first_name' => 'Cynthia'),
		array('id' => '2','first_name' => 'Keith'),
		array('id' => '3','first_name' => 'Robert'),
		array('id' => '4','first_name' => 'Theresa'),
		array('id' => '5','first_name' => 'Margaret')
	);
 
	echo json_encode($data);
?>

As you can see, in this file I’m just manually creating my dataset. Note that I’ve included the line header("Access-Control-Allow-Origin: *"); at the beginning, by doing this I’m avoiding the Cross-Origin Request Blocked error, which is a very common error for people who are getting started with web services, no matter which programming language you are using, if you don’t allow other applications to access your service you’ll see this error.

Now let’s get started with our angular2 application, you probably already have everything set up, but if you don’t, just follow the instructions on the Angular2 Quickstart to create an empty project.

We’re going to need Http Client to be able to send requests to our server, in order to use it on our project we have to register it as a service provider on our main.ts:

import { bootstrap }    from '@angular/platform-browser-dynamic';
import {HTTP_PROVIDERS} from '@angular/http';
import { AppComponent } from './app.component';
bootstrap(AppComponent, [HTTP_PROVIDERS]);

Next let’s create the component, if you followed the instructions from the angular2 quickstart you already have the app.component.ts in your project, just open this file and paste the following code into it:

import {Http, Response} from '@angular/http';
import {Injectable, Component } from '@angular/core';
 
@Component({
  selector: 'my-app',
  template: `<ul>
		<li *ngFor="let person of data">
		   {{person.id}} - {{person.first_name}}
		</li>
	     </ul>`
})
export class AppComponent { 
 
    private data;
 
    constructor(private http:Http){
    }
 
    ngOnInit(){
    	this.getData();
    }
 
    getData(){
        this.http.get('http://localhost/AngularWithPhpTest/')
        		.subscribe(res => this.data = res.json());
    }
}

Most of what’s in this code probably isn’t new for you, so I won’t bother to explain all the basic things again. What matters here is the getData() method, that’s where we’re getting the data from that php web service we created at the beginning.

Now let’s see how it actually works, if you take a look at the code you’ll see that I’ve used two functions to be able to get the data: get() and subscribe(). The first receives the web service url and calls the server to get the data, while the second one specifies the actions that should be taken when it receives the response, in this case I’m just assigning the received data to the this.data variable, pretty simple right?

This was a really simple example, but feel free to leave a comment if you have any doubts. I showed you just how to load a dataset, but there are a lot more that could be done here, you don’t necessary have to get a json dataset as a result, it could be anything you want, and you could also add some parameters to your url and read them on the server-side, that would allow you to send information back and forth between your applications.