Posts on this Category



Angular2 Error: Cannot assign to a reference or variable! ; Zone: <root> ; Task: Promise.then ; Value: Error: Cannot assign to a reference or variable!

This error occurs when you try to define a template reference variable with the same name of an existing variable, like for example in this case:

@Component({
  selector: 'example',
  template: `
        <label for="name">Name</label>
        <input type="text" [(ngModel)]=name #name="ngModel" >
  `
})
export class AppComponent {
	name;
}

As you can see, there’s the template reference variable #name on the input and there’s also a variable called name on my class, this will cause the following error when you try to run the application:

zone.js:355 Unhandled Promise rejection: Cannot assign to a reference or variable! ; Zone: <root> ; Task: Promise.then ; Value: Error: Cannot assign to a reference or variable!() Error: Cannot assign to a reference or variable!
    at _AstToIrVisitor.visitPropertyWrite (http://localhost:3000/node_modules/@angular/compiler/bundles/compiler.umd.js:11686:25)
    at PropertyWrite.visit (http://localhost:3000/node_modules/@angular/compiler/bundles/compiler.umd.js:3156:26)
    at ASTWithSource.visit (http://localhost:3000/node_modules/@angular/compiler/bundles/compiler.umd.js:3342:27)
    at convertCdStatementToIr (http://localhost:3000/node_modules/@angular/compiler/bundles/compiler.umd.js:11483:30)
    at CompileEventListener.addAction (http://localhost:3000/node_modules/@angular/compiler/bundles/compiler.umd.js:11911:29)
    at eval (http://localhost:3000/node_modules/@angular/compiler/bundles/compiler.umd.js:11984:20)
    at Array.forEach (native)
    at collectEventListeners (http://localhost:3000/node_modules/@angular/compiler/bundles/compiler.umd.js:11981:18)
    at ViewBinderVisitor.visitElement (http://localhost:3000/node_modules/@angular/compiler/bundles/compiler.umd.js:12319:11)
    at ElementAst.visit (http://localhost:3000/node_modules/@angular/compiler/bundles/compiler.umd.js:349:26)consoleError @ zone.js:355_loop_1 @ zone.js:382drainMicroTaskQueue @ zone.js:386ZoneTask.invoke @ zone.js:308
zone.js:357 Error: Uncaught (in promise): Error: Cannot assign to a reference or variable!()

The solution for this problem is very simple and obvious, the only thing you have to do is change the name of one of your variables.

Angular2 Error: Can’t bind to ‘ngModel’ since it isn’t a known property of ‘input’.

Lots of people are having this problem since Angular2 introduced NgModule, this error occurs when you try to use something from an specific module without importing it, this is how the error looks on the console:

zone.js:355 Unhandled Promise rejection: Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'input'. ("
        <input type="text" class="form-control" id="name"
               required
               [ERROR ->][(ngModel)]=name name="name" >
        <div [hidden]="name.valid || name.pristine" 
             clas"): FormComponent@4:15 ; Zone: <root> ; Task: Promise.then ; Value: Error: Template parse errors:() Error: Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'input'. ("
        <input type="text" class="form-control" id="name"
               required
               [ERROR ->][(ngModel)]=name name="name" >
        <div [hidden]="name.valid || name.pristine" 
             clas"): FormComponent@4:15
    at TemplateParser.parse (http://localhost:3000/node_modules/@angular/compiler/bundles/compiler.umd.js:8530:21)
    at RuntimeCompiler._compileTemplate (http://localhost:3000/node_modules/@angular/compiler/bundles/compiler.umd.js:16905:53)
    at eval (http://localhost:3000/node_modules/@angular/compiler/bundles/compiler.umd.js:16828:85)
    at Set.forEach (native)
    at compile (http://localhost:3000/node_modules/@angular/compiler/bundles/compiler.umd.js:16828:49)
    at ZoneDelegate.invoke (http://localhost:3000/node_modules/zone.js/dist/zone.js:203:28)
    at Zone.run (http://localhost:3000/node_modules/zone.js/dist/zone.js:96:43)
    at http://localhost:3000/node_modules/zone.js/dist/zone.js:462:57
    at ZoneDelegate.invokeTask (http://localhost:3000/node_modules/zone.js/dist/zone.js:236:37)
    at Zone.runTask (http://localhost:3000/node_modules/zone.js/dist/zone.js:136:47)consoleError @ zone.js:355_loop_1 @ zone.js:382drainMicroTaskQueue @ zone.js:386ZoneTask.invoke @ zone.js:308
zone.js:357 Error: Uncaught (in promise): Error: Template parse errors:()

All you have to do to fix this is to import the FormsModule on your app.module.ts:

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

Tutorial: How to redirect in Angular2

In this tutorial I’m going to give you a very simple example of how to navigate between components on an Angular2 application, but before we begin there are some configurations we have to do.

We’re going to use 2 components in this example: Component1 and Component2, to be able to redirect and navigate from one to the other we’re going to use the RouterModule, and for that module to work we have to create a file called app.routing.ts:

import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { Component1 } from './component1.component';
import { Component2 } from './component2.component';
 
const appRoutes: Routes = [
  { path: 'component1', component: Component1 },
  { path: 'component2', component: Component2 }
];
 
export const appRoutingProviders: any[] = [];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);

This is the file where we can define the routes, it allows us to specify a path for each of our components, as you can see in the code I’ve defined the paths /component1 and /component2 which will allow me to redirect to both my components.

Next we have to import the routing configuration on the app.module.ts as follows:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }   from './app.component';
import { routing, appRoutingProviders }  from './app.routing';
import { Component1 } from './component1.component';
import { Component2 } from './component2.component';
 
@NgModule({
  imports:      [ BrowserModule, routing ],
  declarations: [ AppComponent, Component1, Component2],
  providers:    [appRoutingProviders],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

Perfect! We’re done with the configurations, now you can redirect by passing the path to the routerLink attribute of a regular link:

<a routerLink="/component1" >Component 1</a>
<a routerLink="/component2" >Component 2</a>

This will have the same effect as typing http://localhost:3000/component1 on the browser.

Angular2 Error: No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.

This is a very common error for Angular2 beginners, if you are reading this it’s probably because you’re using the RouterModule module for the first time, you’ve done everything right but when you run your application you see something like this on your firebug:

core.umd.js:3462 EXCEPTION: No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.ErrorHandler.handleError @ core.umd.js:3462(anonymous function) @ core.umd.js:6860ZoneDelegate.invoke @ zone.js:192onInvoke @ core.umd.js:6242ZoneDelegate.invoke @ zone.js:191Zone.run @ zone.js:85(anonymous function) @ zone.js:451ZoneDelegate.invokeTask @ zone.js:225onInvokeTask @ core.umd.js:6233ZoneDelegate.invokeTask @ zone.js:224Zone.runTask @ zone.js:125drainMicroTaskQueue @ zone.js:357ZoneTask.invoke @ zone.js:297
core.umd.js:3467 ORIGINAL STACKTRACE:ErrorHandler.handleError @ core.umd.js:3467(anonymous function) @ core.umd.js:6860ZoneDelegate.invoke @ zone.js:192onInvoke @ core.umd.js:6242ZoneDelegate.invoke @ zone.js:191Zone.run @ zone.js:85(anonymous function) @ zone.js:451ZoneDelegate.invokeTask @ zone.js:225onInvokeTask @ core.umd.js:6233ZoneDelegate.invokeTask @ zone.js:224Zone.runTask @ zone.js:125drainMicroTaskQueue @ zone.js:357ZoneTask.invoke @ zone.js:297
core.umd.js:3468 Error: No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.
    at new PathLocationStrategy (common.umd.js:669)
    at provideLocationStrategy (router.umd.js:3602)
    at NgModuleInjector.get (AppModule.ngfactory.js:125)
    at NgModuleInjector.get (AppModule.ngfactory.js:130)
    at NgModuleInjector.get (AppModule.ngfactory.js:167)
    at NgModuleInjector.get (AppModule.ngfactory.js:177)
    at NgModuleInjector.AppModuleInjector.getInternal (AppModule.ngfactory.js:235)
    at NgModuleInjector.get (core.umd.js:7221)
    at ApplicationRef_._loadComponent (core.umd.js:7070)
    at ApplicationRef_.bootstrap (core.umd.js:7058)ErrorHandler.handleError @ core.umd.js:3468(anonymous function) @ core.umd.js:6860ZoneDelegate.invoke @ zone.js:192onInvoke @ core.umd.js:6242ZoneDelegate.invoke @ zone.js:191Zone.run @ zone.js:85(anonymous function) @ zone.js:451ZoneDelegate.invokeTask @ zone.js:225onInvokeTask @ core.umd.js:6233ZoneDelegate.invokeTask @ zone.js:224Zone.runTask @ zone.js:125drainMicroTaskQueue @ zone.js:357ZoneTask.invoke @ zone.js:297
zone.js:344 Unhandled Promise rejection: No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document. ; Zone: <root> ; Task: Promise.then ; Value: Error: No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.() Error: No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.
    at new PathLocationStrategy (http://localhost:3000/node_modules/@angular/common/bundles/common.umd.js:669:23)
    at provideLocationStrategy (http://localhost:3000/node_modules/@angular/router/bundles/router.umd.js:3602:13)
    at NgModuleInjector.get (AppModule.ngfactory.js:125:77)
    at NgModuleInjector.get (AppModule.ngfactory.js:130:84)
    at NgModuleInjector.get (AppModule.ngfactory.js:167:151)
    at NgModuleInjector.get (AppModule.ngfactory.js:177:132)
    at NgModuleInjector.AppModuleInjector.getInternal (AppModule.ngfactory.js:235:66)
    at NgModuleInjector.get (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:7221:31)
    at ApplicationRef_._loadComponent (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:7070:44)
    at ApplicationRef_.bootstrap (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:7058:18)
zone.js:346 Error: Uncaught (in promise): Error: No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.()

Lucky for you this problem is very easy to solve, you just have to go to your index.html and add the following line on the head:

<head>
  <base href="/">
  ...
</head>

There, problem solved!!

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!

How to Load a JSON file in Angular2

Angular2 makes it very easy for us to load data from JSON files, we can do it by simply making a http request. Now let’s see how we can do that.

To be able to make Http requests we first have to import the HttpModule on the app.module.ts, once you’ve done that your code should look like this:

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

Next you have put your JSON file in a location accessible via Http, you can put it directly on the root folder of your project if you want, I’m going to create a new folder called /data to keep the files organized.

Now you can load you file using http.get() like I did in the constructor:

import {Http} from '@angular/http';
import { Component } from '@angular/core';
 
@Component({
  selector: 'my-app',
  template: ``,
})
export class AppComponent { 
 
    data;
 
    constructor(private http:Http) {
        this.http.get('data/data.json')
                .subscribe(res => this.data = res.json());
    }
 
}

Note that I’ve used the subscribe() function here, it receives another function responsible for handling the response, in this case I’m just assigning it the the data variable.

Very simple, right? I’ve used Angular 2.0.0-rc.6 version for this tutorial, if you are using a different version this may not work for you.

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.