Posts on this Category



Using jQuery with Angular2

I know the idea of using jQuery with Angular2 may seen a little bit weird for lots of you, as we all know, Angular2 is responsible for managing everything related to our view components and DOM elements, it doesn’t sound like a good idea to use another framework to do a job Angular can easily do.

That being said, why would someone want to integrate jQuery with Angular2?

Well, there are some cases we still have to use jQuery, like for example, reusing some jQuery code or components when it’s not feasible to rewrite everything in Angular2, that’s probably the reason why you’re reading this tutorial.

Now let’s see how we can do this, it’s actually really simple, basically all you have to do is to add the jQuery script to your index.html and declare jQuery on your component, here is an example:

import {Component} from 'angular2/core';
 
declare var jQuery:any;
 
@Component({
    selector: 'my-app',
    template: `<button onclick="console.log('It Worked!!')">
                    jQuery Integration Test
               </button>
              `
})
 
export class AppComponent { 
 
    ngAfterViewInit() {
        jQuery('button').click();
    }
}

When you run your application you’ll see the text ‘It Worked!!’ on your console. That’s it!! This was a very short tutorial, but I hope it was helpful for you, just leave a comment if you have any doubts.

Angular2 Tutorial: Developing a Realtime Chat App

Angular 2 Chat Application
Angular 2 Chat Application

Hi guys, today we’re going to make an awesome chat application with Angular2, NodeJS and Socket.io, this tutorial will involve quite a lot of things, and there are also lots of small details, so it will be a little bit longer than usual. To easily understand and make the most of it you should already have some knowledge about all the frameworks involved, if something is unclear for you please let me know in the comments, I’ll try to explain it better. With that in mind let’s stop wasting time and get started!

Setting up the Environment

I’m going to use Express to create my project, if you’re new to express and don’t know how to do it click here to see the instructions. After creating the project there will be a file called package.json on the project folder, that’s where all the dependencies are listed, open this file and copy/paste the following code:

{
  "name": "angular2-chat",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "postinstall": "npm run typings install",
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "start": "concurrent \"node ./bin/www\" \"npm run tsc:w\"",
    "typings" : "typings"
  },
   "license": "ISC",
  "dependencies": {
    "body-parser": "~1.13.2",
    "cookie-parser": "~1.3.5",
    "debug": "~2.2.0",
    "express": "~4.13.1",
    "jade": "~1.11.0",
    "morgan": "~1.6.1",
    "serve-favicon": "~2.3.0",
    "angular2": "2.0.0-beta.16",
    "systemjs": "0.19.26",
    "es6-promise": "^3.0.2",
    "es6-shim": "^0.35.0",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.2",
    "zone.js": "0.6.12",
    "socket.io":"1.4.5"
  },
  "devDependencies": {
    "concurrently": "^2.0.0",
    "lite-server": "^2.2.0",
    "typescript": "^1.8.10",
    "typings":"^0.8.1"
  }
}

Besides the NodeJS and Express dependencies (which were already there), I’ve also added Socket.io and everything related to Angular2. If you run the command npm install on your terminal it’ll download and put all the dependencies on a folder called /node_modules. Lots of scripts from this folder will be used on the front-end, so we have to reference them on the index.html file, which we’re going to create right now.

Open the /views folder and create the index.html with the following code:

<html>
  <head>
    <base href="/">
    <title>Chat</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">   
    <script 
      src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.5/socket.io.min.js"></script> 
    <script src="scripts/es6-shim/es6-shim.min.js"></script>
    <script src="scripts/systemjs/dist/system-polyfills.js"></script>
    <script src="scripts/angular2/bundles/angular2-polyfills.js"></script>
    <script src="scripts/systemjs/dist/system.src.js"></script>
    <script src="scripts/rxjs/bundles/Rx.js"></script>
    <script src="scripts/angular2/bundles/angular2.dev.js"></script>
    <script src="scripts/angular2/bundles/router.dev.js"></script>
    <script src="javascripts/jquery.js"></script>
    <link rel="stylesheet" 
      href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
    <script 
      src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/js/materialize.min.js"></script>
    <script>
      System.config({
        packages: {        
          app: {
            format: 'register',
            defaultExtension: 'js'
          }
        }
      });
      System.import('javascripts/app/main.js')
            .then(null, console.error.bind(console));
    </script>
  </head>
  <body>
    <chat-app>Loading...</chat-app>
  </body>
</html>

This file is very similar to the one from Angular2 Quickstart, but as you can see I’ve added three more scripts: Socket.io and the Materialize css and js files (materialize is a CSS framework we’re going to use for styling). If you pay attention to this code you should notice that I’m not referencing the scripts from /node_modules, instead they’re coming from a folder called /scripts. But where does this folder come from? I’m going to explain in a moment.

One more thing, in order to make Angular2 work you’ll need three more configuration files : tsconfig.json, typings.json and main.ts. All of them can be found on the Angular2 Quickstart.

Now let’s open the app.js file that Exapress created for us, you’ll see that it already has some code, in order to make things easier I’m going to get rid of some lines of code we don’t need, after the modifications the file should look like this:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var app = express();
 
app.use('/scripts', express.static(__dirname + '/node_modules/'));
app.use('/templates', express.static(__dirname + '/views/templates/'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
 
app.use('/', routes);
 
/* Handle 404. */
app.use(function(req, res, next) {
  res.sendFile(path.join(__dirname, 'views', 'index.html'));
});
 
module.exports = app;

Just after the var app = express(); line I’ve configured the paths /scripts (which we saw in the index.html) and /templates to serve some static files from /node_modules and /views/templates respectively. I had to do this because by default Angular 2 won’t have access to these folders. But now, if I request a file from /scripts this configuration will make NodeJS understand that it’s located on /node_modules.

At the end of the code (just above module.exports) I’ve changed how 404 errors are handled, instead of forwarding an error (as it was before) I’m redirecting to index.html. This will avoid some problems when we start using Angular2 routes.

Another thing we have to do is to make NodeJS and Angular2 work together, open the file /routes/index.js and replace the existing code with the following:

var express = require('express');
var router = express.Router();
var path = require('path');
 
/* GET home page. */
router.get('/', function(req, res, next) {
  res.sendFile(path.join(__dirname, '../', 'views', 'index.html'));
});
 
module.exports = router;

By default it was rendering a .jade file (express uses jade as the default view engine), and as I’m not interested in jade for this project I just changed this file a little bit in order to make it redirect to my index.html where Angular2 can control the views. For more details about this modification click here.

At this point we’ve already configured everything we need in our project to start developing our chat app, new let’s start talking about how the application is going to work.

Defining the Structure

Our chat app will be composed of three Angular2 components, the first one will be a form where the user will be allowed to enter his name and join the chat, the second will be the chat itself, and the last will be where we’re going to configure to routes for controlling which of the other two components should be displayed.

On the back-end we’ll have Socket.io being responsible for receiving the messages and delivering them to all the other users, we won’t store the messages there, each client will have its own messages list where every received message will be added.

Creating the Socket.io Server

Before we proceed to the front-end we first have to create the Socket.io server and prepare it to receive messages from the clients, to do that you have to create a new file on your project root folder called socket.js with the following code:

var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);
 
var chat = {
	start: function(){
		server.listen(8000);
		io.set("origins", "*:*");
 
		io.on('connection', function (socket) {         // line 12
			socket.on('newMessage', function (data) {
				socket.emit('chatUpdate',data);
				socket.broadcast.emit('chatUpdate',data);
			});
			socket.on('newUser', function (data) {
				socket.emit('chatUpdate',
					{'userName':'','text':data+' has entered the room'});
				socket.broadcast.emit('chatUpdate',
					{'userName':'','text':data+' has entered the room'});
			});
		});	
	}
}
 
module.exports = chat;

Now probably is the best time for me to explain how Socket.io works, according to the official site Socket.IO is a framework that enables real-time bidirectional event-based communication, in other words you can create your own events that will allow the server to communicate with the clients and vice-versa. You can add listeners to these events and also emit events from both sides (client and server), once an event is emitted it will trigger its listener on the other side to execute an specific task. To emit events you can use the function emit() passing the event name and your data, and to add a listener you have to use the function on() with the event name as the first parameter and the callback function as the second.

Easy, right? Now that you understand how Socket.io works let’s analyze our code. The first thing I did here was to create a socket.io server that listens on port 8000, but let’s focus on the events, on the server side there is one event that we always have to use in order to start the communication with the clients, this event is called connection, it will be automatically emitted by the each client when it connects to the server (obviously), clearly we have to add a listener to proceed with the communication, as you can see in the code I’m doing it on line 12. Now take a look at the callback function associated with this listener, you’ll see that it’s registering listeners for two more events: newMessage and newUser. The first one is emitted when a user sends a message, and the second one when a new user joins the chat, the action performed by both is very similar, they will just emit another event called chatUpdate to notify all the connected clients about the new message or user. Note that when I emit this event I’m using both socket.emit() and socket.broadcast.emit(), the first one will notify the client who triggered the event, and the second will do the same to all the other clients.

Let’s add the following two lines bellow the var app = express(); on our app.js:

var socketServer = require('./socket');
socketServer.start();

Perfect! This will make the socket.io server initialize right after the application starts. We’re done with the back-end now, let’s start creating the angular2 components.

Creating the User Registration Component

We can finally start writing some Angular2 code, open the /public/javascripts folder and create a new one called /app, that’s where we’re going to put our angular2 components. Open this new folder and add a new file called userRegistration.component.js, then copy/paste the following code:

import {Component} from 'angular2/core';
import {Router} from 'angular2/router';
 
@Component({
    selector: 'user-registration',
    templateUrl: 'templates/registration.html'
})
export class UserRegistrationComponent {
    userName = '';
    socket = null;
 
    constructor(
        private _router: Router){}
 
    ngOnInit() {
        this.socket = io('http://localhost:8000');
    }
 
    login() {
        if (this.userName !== null){
            sessionStorage.setItem("userName", this.userName);
            this._router.navigate(['Chat']);
            this.socket.emit('newUser', this.userName);
        }
    }
 
    keypressHandler(event) {
        if (event.keyCode  === 13){
            this.login();
        }
    } 
}

This will be the component where the user is going to enter his name and join the chat, I’ve used the hook ngOnInit to connect to the Websocket server, this will automatically emit the connection event I just talked about. I also have the login() method, which is responsible for putting the provided userName on the sessionStorage and emit the newUser event. Although I’m using the sessionStorage to store the user, I don’t recommend you to do it, it’s not very safe, any user with some javascript knowledge will be able to modify what’s in the sessionStorge.

Note that I’ve created a new file to put the template, it’s called registration.html and it’s located on the folder /views/templates, here’s the code:

<style type="text/css">
	.registrationContainer{margin-top:20%;padding:15px;box-shadow: 3px 2px 7px -1px}
	.registrationContainer button{float: right;}
</style>
<div class="container">
	<div class="col s11 registrationContainer">
 
        <div class="row">
            <div class="input-field col s12">
                <input [(ngModel)]="userName" id="userName" 
                	type="text" (keypress)="keypressHandler($event)">
                <label for="userName">Please enter your name</label>
            </div>
        </div>
	    <button (click)="login()" type="submit" 
	    	class="btn waves-effect waves-light col s3"  
	    	name="action" >Login</button>
	    <div style="clear:both;"></div>
	</div>
</div>

Nothing special here, just an input where the user can type his name and a button to call the login() function. The CSS classes you can see here are from materialize.

Creating the Chat Component

Now comes the most important part, the chat.component.ts:

import {Component} from 'angular2/core';
import {Router} from 'angular2/router';
 
@Component({
    selector: 'chat',
    templateUrl: 'templates/chat.html'
})
export class ChatComponent {
    message = '';
    conversation = [];
    socket = null;
 
    constructor(
        private _router: Router){}
 
    ngOnInit() {
        if (sessionStorage.getItem("userName") === null){
            this._router.navigate(['Registration']);
        }
        this.socket = io('http://localhost:8000');
        this.socket.on('chatUpdate', function(data) {
            this.conversation.push(data);
        }.bind(this));
    }
 
    send() {
        this.socket.emit('newMessage', {
            'userName': sessionStorage.getItem("userName"),
            'text': this.message
        });
        this.message = '';
    }
 
    keypressHandler(event) {
        if (event.keyCode === 13){
            this.send();
        }
    } 
 
    isNewUserAlert(data){
        return data.userName === '';
    }
}

Again I’m using the ngOnInit hook to connect to server, but this time there are a couple more things I’m doing here, I’m checking the sessionStorage to see if it contains the userName, if it doesn’t the user will be redirected to the registration component, and I’m also adding a listener to the chatUpdate event, so when a new message arrives it’ll be added to the conversation array.

The send() method is responsible for triggering the newMessage event, it just get the message typed by the user and send it to the server, it’ll be executed when the user click on the send button or press enter.

Here’s the template:

<style type="text/css">
	.userLabel{font-weight:bold;color:#26A69A;margin-right:10px}
	.chatContainer{height:85%;padding:15px;overflow-y:auto }
</style>
<div class="col s12">
	<div class="col s12 chatContainer">
        <ul *ngFor="#msg of conversation" style="margin:0">
            <li >
            	<div *ngIf="!isNewUserAlert(msg)">
	                <span  class="userLabel" >{{msg.userName}}:</span>
	                <span>{{msg.text}}</span>
                </div>
            	<div *ngIf="isNewUserAlert(msg)">
            		<span style="font-weight:bold">{{msg.text}}</span>
	            </div>
            </li>
        </ul>
	</div>
	<div class="row">
		<div class="col s9">
          <input id="country" type="text"  
          	[(ngModel)]="message" 
          	(keypress)="keypressHandler($event)">
        </div>
		<button (click)="send()"  type="submit" 
			class="btn waves-effect waves-light s2"  name="action" >Send</button>
	</div>
</div>

Lastly we have the component app.component.ts to control the routing, with RouteConfig I’m defining the two possible routes of our app, this allows the other components to redirect from one to another. Note that in the template I have only the router-outlet which will basically render the component related to the current route.

import {Component} from 'angular2/core';
import {UserRegistrationComponent} from 'javascripts/app/userRegistration.component.js';
import {ChatComponent} from 'javascripts/app/chat.component.js';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
 
@Component({
    selector: 'chat-app',
    directives: [ROUTER_DIRECTIVES],
    template: `
            <router-outlet></router-outlet>
        `
})
@RouteConfig([ 
    { path: '/chat', name: 'Chat', component: ChatComponent, useAsDefault:true },
    { path: '/registration', name: 'Registration', component: UserRegistrationComponent }
])
export class AppComponent {}

To make the routes work we have to make a little modification in our main.ts, just add the ROUTER_PROVIDERS as follows:

import {bootstrap}    from 'angular2/platform/browser'
import {AppComponent} from 'javascripts/app/app.component.js'
import {ROUTER_PROVIDERS} from 'angular2/router'
 
bootstrap(AppComponent, [ROUTER_PROVIDERS]);

That’s it guys, we’ve completed our chat app, to run it just execute npm start and access it on your browser by typing localhost:3000. If you have any doubts please let me know in the comments, till next time!

Tutorial: Creating an Angular2 Autocomplete

Angular 2 Autocomplete
Angular 2 Autocomplete

Before we begin I just want to say that I’m not going to use any third-party component for this tutorial, I’m going to create an autocomplete from scratch, my goal is to just make it show the suggestions and allow the user to select one, but if you need more advanced features feel free to comment, I’ll do what I can to help you.

With that in mind, let’s start by creating our class, just copy/paste the code bellow:

export class AutocompleteComponent {
    public query = '';
    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"];
    public filteredList = [];
    public elementRef;
 
    constructor(myElement: ElementRef) {
        this.elementRef = myElement;
    }
}

As you can see I’ve already added the data to my class, as I’m trying to make it simple it’s just an array of countries, but of course in a real case scenario the data would come from your database or via web service, also it wouldn’t be placed inside the component, it would be passed to it, this way the component could be reused with other data in other parts of the application.

I’ve also created the variables query and filteredList, the first one will hold the string typed by the user, and the second is where I’m going to store the suggestions being displayed by the component, its value will constantly change as the user types on the input. There is also the constructor where I’m setting the elementRef value, but I’ll get to that variable in a moment.

Now let’s create the methods to filter the data and select the item:

filter() {
    if (this.query !== ""){
        this.filteredList = this.countries.filter(function(el){
            return el.toLowerCase().indexOf(this.query.toLowerCase()) > -1;
        }.bind(this));
    }else{
        this.filteredList = [];
    }
}
 
select(item){
    this.query = item;
    this.filteredList = [];
}

These two functions are very straightforward, the filter() function uses the query variable to filter the countries, then it stores the result in the filteredList.

The select() is even simpler, I’m just assigning the selected item to the query variable in order to make it appear on the input, and to make the suggestions list disappear I’m removing everything from the filteredList.

Ok, we already have the two most important functions to make our component work, now we can create the template:

@Component({
    selector: 'autocomplete',
    template: `
        <div class="container" >
            <div class="input-field col s12">
              <input id="country" type="text" class="validate filter-input" [(ngModel)]=query (keyup)=filter()>
              <label for="country">Country</label>
            </div>
            <div class="suggestions" *ngIf="filteredList.length > 0">
                <ul *ngFor="#item of filteredList" >
                    <li >
                        <a (click)="select(item)">{{item}}</a>
                    </li>
                </ul>
            </div>
        </div>  	
        `
})

Note that I’ve used some different css classes here, some of them I created myself and some are from materialize, if you want to use them just add to your project the link to their css and js files.

At this point your autocomplete is already working, if you run your project you’ll see a result similar to the gif at the beginning of this tutorial, but there’s still a small problem we have to fix, note that once the suggestions list shows up you have to either erase the text from the input or select one to make the them disappear. The problem is that the user should be able to get rid of the suggestions by clicking anywhere other than the list, and to be able to do that we have to detect clicks outside the our component, more info here.

Remember the elementRef variable we saw in the constructor? Now we’re going to use it, the follwoing method tells whether the click occured in the component or outside it:

handleClick(event){
   var clickedComponent = event.target;
   var inside = false;
   do {
       if (clickedComponent === this.elementRef.nativeElement) {
           inside = true;
       }
      clickedComponent = clickedComponent.parentNode;
   } while (clickedComponent);
    if(!inside){
        this.filteredList = [];
    }
}

The function just gets the clicked component, navigates between its parent nodes and checks if one of them is the elementRef.nativeElement (which is our component), if it’s true the items from the filteredList are deleted in order to make the list disappear. Now we have to bind this method to the (document:click) event, this is how you can do it:

@Component({
    selector: 'autocomplete',
    host: {
        '(document:click)': 'handleClick($event)',
    },
    template: //TEMPLATE CODE HERE
})

That’s it!! As I said if you need more features or if you have any doubts just leave a comment, I’ll be glad to help!

Angular2 Tutorial: Detecting Clicks Outside the Component

Angular2 click detection
Angular2 click detection

Sometimes there is a need to detect whether the user is clicking inside or outside our angular2 component, specially if your component has a dropdown element, in this case you need to know exactly where the click occurred in order to perform the right action. In this tutorial I’m going to demonstrate with angular 2 a very easy way to determine if the click happened outside the component or not.

Let’s start by creating this very simple component:

import {Component, ElementRef} from 'angular2/core';
 
@Component({
    selector: 'click-detection-component',
    template: `
    	<div style="width:100px;height:60px;background-color:#f1f1f1"></div>
    	`
})
 
export class ClickDetectionComponent {
}

Nothing special here, it just renders a rectangle on the screen. Now my goal will be to show a different message when the click occurs inside and outside this rectangle, to do that we have to create a function to check if the clicked component belongs to my current angular2 component or not:

export class ClickDetectionComponent {
   public elementRef;
 
   constructor(myElement: ElementRef) {
       this.elementRef = myElement;
   }
 
   handleClick(event){
       var clickedComponent = event.target;
       var inside = false;
       do {
           if (clickedComponent === this.elementRef.nativeElement) {
               inside = true;
           }
           clickedComponent = clickedComponent.parentNode;
       } while (clickedComponent);
       if(inside){
           console.log('inside');
       }else{
           console.log('outside');
       }
   }
}

Here’s what is happening in this function: First I’m getting the clicked component from my event using event.target, then I’m navigating between its parent nodes checking is one of them is my elementRef.nativeElement, if it is, it means that the user clicked inside the component, otherwise it was outside.

Now comes the tricky part, if I bind this function to the div click event it will only be called when the user clicks on the div, therefore how am I going to be able to detect the clicks that occurs outside? To solve that I’m going to use the (document:click) event, this way the function will be called no matter where the user clicks.

You can add this event to your component like this:

@Component({
    selector: 'click-detection-component',
    host: {
        '(document:click)': 'handleClick($event)',
    },
    template: `
    	<div style="width:100px;height:60px;background-color:#f1f1f1"></div>
    	`
})

Perfect! Now if you run your project you can see the messages on the console telling whether the component was clicked or not.

Hope you enjoyed the tutorial, just leave a comment if you have any doubts.

Angular2 Tutorial: Creating Custom Pipes

Angular 2 Pipes provide us a very simple way to transform/format the data displayed by our application, there are some built-in pipes we can use, but sometimes they don’t meet our needs, that’s when we have to create custom pipes. This will be a very quick tutorial in which I’ll give you an example of how you can create your own pipes.

I’m assuming you already have your angular2 project, but if you don’t, just follow the instructions on the official site to create a starter project. Make sure the project is working before you proceed.

As an example I’m going to create a pipe to limit the amount of characters on a string, let’s assume you have limited space on your page and there is no way for you to display the entire text, you’ll just provide the maximum amount of characters and the pipe will take care of the rest, every time you come across this situation you can use this pipe to make the text fit on the space you have available.

Let’s start by creating in our app folder a file called maxLength.pipe.ts, copy/paste the following code into it:

import {Pipe} from 'angular2/core';
 
@Pipe({
    name: 'maxLength'
})
export class MaxLengthPipe {
    transform(val, args) {
        if (val.length > 30){
            return val.substring(0, 30)+'...';    
        }else{
            return val;
        }
    }
}

Perfect, you already have a pipe!! All you had to do was to create a class and put the @Pipe decorator on it, but to make it work we also have to implement the transform function, that’s where we are going to put our logic. In this simple example I’m just checking if my text has a length greater than 30, if it does I’m returning the first 30 characters.

That’s enough for us to be able to use our pipe, open your app.component.ts and paste the following code:

import {Component} from 'angular2/core';
import {MaxLengthPipe} from './maxLength.pipe';
 
@Component({
    selector: 'my-app',
    template: `<p>{{value | maxLength}}</p>`,
    pipes: [MaxLengthPipe]
})
 
export class AppComponent { 
    public value = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi vel dui '
                  +'at sem placerat dictum dictum placerat est. Mauris pretium mattis nulla '
                  + 'vel suscipit.Vestibulum laoreet congue erat, eget bibendum justarius id';   
}

That’s the simplest possible example, I have a class with just one attribute which will store my text. Note how I used the pipe in the template, I just wrote the name of my variable followed by the pipe name we specified in the @Pipe decorator, which in this case was maxLength.

If you run the project you’ll see that it’s already working, but we can improve it a little bit more, instead of always returning the first 30 characters, we can pass a parameter to the pipe telling how many characters we want. To do that we have to modify our transform function, everywhere we were using the number 30 we have to replace it by args[0], this is how it should look like:

transform(val, args) {
    if (val.length > args[0]){
        return val.substring(0, args[0])+'...';    
    }else{
        return val;
    }
}

Then in the app.component.js you can pass the parameter like this:

{{value | maxLength : 30}}

That’s it!! Hope you enjoyed the tutorial, leave a comment if you have any doubts.

Tutorial: Angular 2 Datatable with Sorting, Filtering and Resizable Columns

In this tutorial I’m going to show you one of the datatable solutions available for Angular 2, it’s called ag-Grid and it’s available not only for angular2, but also for other frameworks like Angular 1 and React. It’s a really complete datatable, it has lots of features that I definitely want to explore in other tutorials, but in this one I’ll try to keep it as simple as possible, my goal is to just make it display the data and enable the sorting, filtering and the resizable columns features. Maybe in the future I’ll write a PART 2 of this tutorial explaining how to add some more complex functionality. If you don’t want to use ag-grid take a look at this post.

I’m assuming you already have your Angular 2 project ready, but if you don’t just follow the instructions on this link to set up your environment, it’s really easy and straightforward, all you need to do is to create three configurations files: tsconfig.json, typings.json and package.json, make sure you have all of them before you continue.

Now let’s add the ag-grid to the project, to do that you have to add these two lines to the dependencies list on your package.json:

{
  "dependencies": {
    "ag-grid": "3.3.x",
    "ag-grid-ng2": "3.3.x"
    ...
  },
}

Run npm install to download and install the dependencies, when it completes we’ll be ready to start writing some code!

Open your project folder and create another one inside called app, that’s where we’re going to put all our Angular2 related code. The first file we are going to create on this folder is the app.component.ts, it should contain the following code, just copy and paste it into the file:

import {Component} from 'angular2/core';
import {AgGridNg2} from 'ag-grid-ng2/main';
 
@Component({
    selector: 'my-datatable',
    directives: [AgGridNg2],
    template: `
         <ag-grid-ng2 #agGrid style="height:100%;width:845px" class="ag-fresh"
            [gridOptions]="gridOptions">
         </ag-grid-ng2 >
     `
})
 
export class AppComponent { 
    myRowData = [
        {"name":"Ronald Bowman","country":"China","city":"Lutou","email":"rbowman0@spotify.com"},
        {"name":"Pamela Hill","country":"Russia","city":"Krylovskaya","email":"phill1@symantec.com"},
        {"name":"Robin Andrews","country":"Ukraine","city":"Korop","email":"randrews2@photobucket.com"},
        {"name":"Peter Kim","country":"Mexico","city":"San Jose","email":"pkim3@theatlantic.com"},
        {"name":"Carol Foster","country":"Mexico","city":"El Aguacate","email":"cfoster8@intel.com"},
        {"name":"Jimmy Burke","country":"Indonesia","city":"Banjarsari","email":"jburke9@over-blog.com"},
        {"name":"Jonathan Crawford","country":"Peru","city":"Alca","email":"jcrawforda@deliciousdays.com"},
        {"name":"Donald Montgomery","country":"Poland","city":"Działoszyce","email":"dmontgomeryb@google.com.br"},
        {"name":"Donna Shaw","country":"Japan","city":"Akune","email":"dshawc@chronoengine.com"},
        {"name":"Helen King","country":"United States","city":"Hollywood","email":"hkingd@devhub.com"},
        {"name":"Walter Myers","country":"China","city":"a ndaowa n", "email":"wmyerse@state.tx.us"},
        {"name":" Alice Collins","country":"Papua Nw  Guine a", "city":"Mendi","email":"acollinsf@npr.org"},
        {"name":"Anne Richards","country":"China","city":"Koramlik","email":"arichardsu@vinaora.com"},
        {"name":"Randy Miller","country":"Indonesia","city":"Trenggulunan","email":"rmillerv@oakley.com"},
        {"name":"Phillip Adams","country":"Bahamas","city":"Duncan Town","email":"padamsw@lycos.com"},
        {"name":"Nicholas Allen","country":"Philippines","city":"Bautista","email":"nallenx@aboutads.info"},
        {"name":"Lisa Willis","country":"Thailand","city":"Lat Yao","email":"lwillisy@istockphoto.com"},
        {"name":"Jeffrey Castillo","country":"Indonesia","city":"Karangsari","email":"jcastilloz@washington.edu"},
        {"name":"Michael Carpenter","country":"Colombia","city":"Cali","email":"mcarpenter13@prlog.org"},
        {"name":"Roger Lee","country":"France","city":"Courtaboeuf","email":"rlee14@earthlink.net"},
        {"name":"Steve Wallace","country":"Russia","city":"Novobeysugskaya","email":"swallace15@cisco.com"},
        {"name":"Shirley Patterson","country":"Peru","city":"La Tinguiña","email":"spatterson16@woothemes.com"},
        {"name":"Nancy Ward","country":"Sweden","city":"Båstad","email":"nward17@mapquest.com"}
    ];
 
    columnDefs = [
        {headerName: 'Name', field: "name", width: 200 },
        {headerName: 'Country', field: "country" ,width:180},
        {headerName: 'City', field: "city" ,width:160},
        {headerName: 'e-mail', field: "email" ,width:300}
    ];
 
    gridOptions = [];
 
    constructor() {
        this.gridOptions = {
            rowData: this.myRowData,
            columnDefs: this.columnDefs,
            enableColResize: true,
            enableSorting: true,
            enableFilter: true
        }   
    }
}

There is quite a lot to explain about this code, I’m going to start with the class AppComponent, that’s where we’re going to put all the parameters and configurations that makes our datatable work, we have three variables on this class: myRowData, columnDefs and gridOptions.

myRowData: This variable will store the data to be displayed on the table, for this example I’m just going to use some JSON data I generated, but in a real case scenario you would get the data from your database or a web service.

columnDefs: This one will store an object containing information about every column of our datatable, I’m just using the attributes headerName to define the column title, field to tell which array attribute will be displayed on the column and width to define the size of each column. Although I’m using only three, there are tons of other attributes you could specify here.

gridOptions: This one just wraps everything up and make it available to the component. It’s being initialized empty, but in the constructor I’m setting its value, besides the rowData and columnDefs I’m also specifying the attributes enableColResize, enaleSorting and enableFilter. They will do exactly what their names suggests, enable the columns resize, sorting and filtering features respectively.

Now we can create our component, to be able to use the directive AgGridNg2 we have import it first with the line import {AgGridNg2} from 'ag-grid-ng2/main, after that all you need to do is to pass the gridOptions to the ag-grid-ng2 component on the template.

Before we write the index.html we’re going to need one more ts file to be able to launch our application, on your app folder create the file main.ts and paste the following code into it:

import {bootstrap}    from 'angular2/platform/browser'
import {AppComponent} from './app.component'
 
bootstrap(AppComponent);

Now you can create the index.html file on your project root folder, let’s take a look at the code:

<html>
  <head>
    <title>Datatable</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">    
    <script src="node_modules/es6-shim/es6-shim.min.js"></script>
    <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
    <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script src="node_modules/rxjs/bundles/Rx.js"></script>
    <script src="node_modules/angular2/bundles/angular2.dev.js"></script>
    <link href="node_modules/ag-grid/dist/styles/ag-grid.css" rel="stylesheet" />
    <link href="node_modules/ag-grid/dist/styles/theme-fresh.css" rel="stylesheet" />
    <script>
      System.config({
        packages: {        
          app: {
            format: 'register',
            defaultExtension: 'js'
          },        
          lib: {
            format: 'register',
            defaultExtension: 'js'
          },
          'ag-grid-ng2': {
            defaultExtension: "js"
          },
          'ag-grid': {
            defaultExtension: "js"
          }
        },
        map: {
            'ag-grid-ng2': 'node_modules/ag-grid-ng2',
            'ag-grid': 'node_modules/ag-grid'
        }
      });
      System.import('app/main')
            .then(null, console.error.bind(console));
    </script>
  </head>
  <body>
    <my-datatable>Loading...</my-datatable>
  </body>
</html>

This file will basically be used just to load the necessary scripts and to configure SystemJS to load everything and launch the application. Finally you can use your component here calling it by the selector we specified before: my-datatable.

We’re done!! To run the project open your terminal, navigate to your project folder and run npm start, this should be the result: my-datatable.

Angular 2 Datatable with Sorting, Filtering and Resizable Columns
Angular 2 Datatable with Sorting, Filtering and Resizable Columns

Creating a Live Auction App with Angular 2, Node.js and Socket.IO

Angular 2 Auction App
Angular 2 Auction App

In this tutorial we’re going to build a very cool Live Auction Application, my goal is to demonstrate how Angular 2, Node.js and Socket.io work together, and as everyone knows Angular 2 will soon come out so I thought it would be great to write a tutorial involving it. Of course our app won’t have all the features a real auction app has, this is just an example to demonstrate how to integrate the frameworks I mentioned.

Setting up the Environment

The first step is to configure the environment, let’s get started by creating our Node.js project, I’m going to use express to do it, if you don’t have it open your terminal and run the command npm install express-generator -g to install, then you can create the project with the command expess {project name} (replace {project name} with your actual project name).

Now you have the basic project structure created for you, but we need to make some changes in order add Angular 2 and Socket.io to the project, first open your package.json and paste the following code:

{
  "name": "auction",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "postinstall": "npm run typings install",
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "start": "concurrent \"node ./bin/www\" \"npm run tsc:w\"",
    "typings" : "typings"
  },
   "license": "ISC",
  "dependencies": {
    "body-parser": "~1.13.2",
    "cookie-parser": "~1.3.5",
    "debug": "~2.2.0",
    "express": "~4.13.1",
    "jade": "~1.11.0",
    "morgan": "~1.6.1",
    "serve-favicon": "~2.3.0",
    "angular2": "2.0.0-beta.6",
    "systemjs": "0.19.20",
    "es6-promise": "^3.0.2",
    "es6-shim": "^0.33.3",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.0",
    "zone.js": "0.5.14",
    "socket.io":"1.4.5"
  },
  "devDependencies": {
    "concurrently": "^1.0.0",
    "lite-server": "^2.0.1",
    "typescript": "^1.7.5",
    "typings":"^0.6.8"
  }
}

Now create another file called tsconfig.json in the project root folder and put the following into the file:

{
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules",
    "typings/main",
    "typings/main.d.ts"
  ]
}

Also in the root folder create the typings.json and copy/paste the following code into it:

{
  "ambientDependencies": {
    "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim
/es6-shim.d.ts#6697d6f7dadbf5773cb40ecda35a76027e0783b2"
  }
}

Ok, we have now created all the configuration files, but before we continue you have to install the dependencies by running the command npm install on the terminal.

If you open your app.js you’ll see that express has already put some code in there, in order to make it as simple as possible let’s delete the code we don’t need, after the modification your app.js should look like this:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var app = express();
 
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
 
app.use('/', routes);
 
// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});
 
module.exports = app;

By default express sets jade as the view engine, we’ve already deleted the lines responsible for that in the app.js, but if you check the folder /views you’ll see some .jade files, you can delete them if you want, later we’re going to place our Angular 2 HTML pages in this folder, but for now you can just create and leave an empty index.html in there.

After getting rid of the .jade files we have to tell Node.js that we want to use our index.html instead, we can do that by changing a little bit the code in the routes/index.js file, just open the file and replace its content with the following code:

var express = require('express');
var router = express.Router();
var path = require('path');
 
/* GET home page. */
router.get('/', function(req, res, next) {
  res.sendFile(path.join(__dirname, '../', 'views', 'index.html'));
});
 
module.exports = router;

To make sure it’s working run your project with the command npm start then enter the url http://localhost:3000/ in your browser, it should display an empty page, write something in the index.html you created and refresh the page, if it appears on the browser you’ve done everything right! Now we’re ready to actually start writing some code.

Introducing Socket.IO

As we know, an auction app must be real-time, which means that when a user places a bid all the other connected users must instantly see it, that’s where Socket.IO comes in, it allows Node.js to receive and broadcast events to all connected clients, so when a user places a bid Socket.IO will emit an event to the server which will update the product price and broadcast it to the other users.

Now let’s see how that looks like in code, copy the following code and paste bellow the var app = express(); in your app.js:

var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(8000);
io.set("origins", "*:*");
 
var currentPrice = 99;
 
io.on('connection', function (socket) {
	socket.emit('priceUpdate',currentPrice);
	socket.on('bid', function (data) {
		currentPrice = parseInt(data);
		socket.emit('priceUpdate',currentPrice);
		socket.broadcast.emit('priceUpdate',currentPrice);
	});
});

In the first 5 lines I’m just creating the server that Socket.IO will use to send/receive events, then I’m creating a listener to the connection event which will be emitted every time a user connects (we’ll get to that in a moment), you can use the function io.on(event, callback) to create a listener to any event you want, you just need to pass the event as the fist argument and the callback function as the second, when it receives the event the callback will be executed.

In this case when a user connects I’m immediately emitting the event priceUpdate passing the current price, that’s because at this moment the client-side doesn’t have the current price yet, so that’s the first thing we want to send. After that we have to create a listener to the bid event that will update the price and broadcast to the other users. Note that I’m calling socket.emit() and socket.broadcast.emit(), the first one will return the updated price to the user that triggered the event, and the second will do the same to all the other users.

Writing our First Angular 2 Component

Now that we have our server-side ready we can get started with Angular 2, let’s create a folder called app inside public/javascripts/ on our project, that’s where we’re going to put all our Angular 2 code. Now create a file and name it app.component.ts, then paste the following code into it:

import {Component} from 'angular2/core';
 
@Component({
    selector: 'auction-app',
    templateUrl: 'templates/product.html'
})
 
export class AppComponent {
    price: number = 0.0;
    socket = null;
    bidValue = '';
 
    constructor(){
        this.socket = io('http://localhost:8000');
        this.socket.on('priceUpdate', function(data){
            this.price = data;
        }.bind(this));    
    }
 
    bid(){
        this.socket.emit('bid', this.bidValue);
        this.bidValue = '';
    }
}

When declaring a @Component, you have to pass an object containing two attributes selector and templateUrl (or just template), the selector is the name we’re going to use to call our component, in this case it’s auction-app, and the templateUrl is the HTML implementation, you can put your HTML code directly on the object or you can put it in a separated file like I did.

We also have in this code the AppComponent class, that’s kind of the ‘controller’ of our component, in the constructor I’m connecting to the Socket.IO from the server using the method io('http://localhost:8000'), this will emit the connection event we saw before, then I’m creating a listener to the priceUpdate event, the server will emit it right after the connection, remember? When Angular receives the updated price it will assign it to the price variable. This class also contains the bid() function, it will just emit the bid event passing the bidValue.

I forgot to mention that I created the /template folder inside /views, the problem is that our component doesn’t have access to it, to solve this problem we have to make this folder a static route on our server, open your app.js and add this line:

app.use('/templates', express.static(__dirname + '/views/templates/'));

Now let’s take a look on our template, I’ll not show the full HTML code here, just the lines that interact with our AppComponent class.

<h1>$ {{price}}</h1>	        
<input  [(ngModel)]="bidValue" >
<button (click)="bid()">Place Bid</button>

There is not much to explain here, the syntax resembles a lot the first Angular, our input uses the attribute [(ngModel)] to reference the bidValue variable from our class, and the button uses the (click) to call the function bid().

To be able to launch our application we have to create a file called main.ts on the public/javascripts/ folder, just copy/paste the following into the file:

import {bootstrap}    from 'angular2/platform/browser'
import {AppComponent} from './app.component.js'
 
bootstrap(AppComponent);

Finally we can write our index.html, you have already created it in the beginning, remember? It’s located on the /views folder, open it and add the following code:

<html>
  <head>
    <title>Live Auction</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">   
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.5/socket.io.min.js"></script> 
    <script src="scripts/es6-shim/es6-shim.min.js"></script>
    <script src="scripts/systemjs/dist/system-polyfills.js"></script>
    <script src="scripts/angular2/bundles/angular2-polyfills.js"></script>
    <script src="scripts/systemjs/dist/system.src.js"></script>
    <script src="scripts/rxjs/bundles/Rx.js"></script>
    <script src="scripts/angular2/bundles/angular2.dev.js"></script>
    <script src="javascripts/jquery.js"></script>
    <script src="javascripts/bootstrap.min.js"></script>
    <link href="stylesheets/bootstrap.min.css" rel="stylesheet">
    <link href="stylesheets/portfolio-item.css" rel="stylesheet">
    <script>
      System.config({
        packages: {        
          app: {
            format: 'register',
            defaultExtension: 'js'
          }
        }
      });
      System.import('javascripts/app/main.js')
            .then(null, console.error.bind(console));
    </script>
  </head>
  <body>
    <auction-app>Loading...</auction-app>
  </body>
</html>

Once again we have to edit the app.js file to be able to load the scripts directly from the node_modules folder, add the following line like we did before:

app.use('/scripts', express.static(__dirname + '/node_modules/'));

This file is pretty simple, we have a script that configures System.js to load our application, and in the body we can call our component by the selector we specified before: auction-app.

Now we’re done!! You can run your application by opening your terminal and running the command npm start, the result should similar to the gif in the beginning of this tutorial.

Just leave a comment if you have any problems, I’ll be glad to help!!