Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

<head>
<meta charset="UTF-8">
<base href="/">
<title>Angular 2 - Countries and Capitals</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 1. Load libraries -->
Expand All @@ -15,6 +16,9 @@
<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>
<script src="/node_modules/angular2/bundles/router.dev.js"></script>
<script src="node_modules/angular2/bundles/http.dev.js"></script>


<!-- 2. Configure SystemJS -->
<script>
Expand Down
22 changes: 22 additions & 0 deletions src/app/app-footer/app-footer.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Component, OnInit } from 'angular2/core';
import {ROUTER_DIRECTIVES,Router} from 'angular2/router';
@Component({
moduleId: 'appFooterModule',
selector: 'app-footer',
templateUrl: 'src/app/app-footer/app-footer.view.html',
styleUrls:['src/app/app-footer/app-footer.styles.css'],
directives: [ROUTER_DIRECTIVES]
})
export class AppFooterComponent implements OnInit {
constructor(public router: Router) {

}
ngOnInit() { }


// this function returns whether the current route is the route passed in the function
isActive(route: any[]): boolean {
return this.router.isRouteActive(this.router.generate(route));
}

}
Empty file.
4 changes: 4 additions & 0 deletions src/app/app-footer/app-footer.view.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div class="text-center">
<a class="btn" [routerLink]="['Home']" *ngIf="!isActive(['Home'])">Home</a>
<a class="btn" [routerLink]="['Countries']" *ngIf="!isActive(['Countries'])">Browse Countries</a>
</div>
14 changes: 14 additions & 0 deletions src/app/app-header/app-header.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Component, OnInit } from 'angular2/core';
import {ROUTER_DIRECTIVES} from 'angular2/router';
@Component({
moduleId: 'appHeaderModule',
selector: 'app-header',
templateUrl: 'src/app/app-header/app-header.view.html',
styleUrls:['src/app/app-header/app-header.styles.css'],
directives: [ROUTER_DIRECTIVES]
})
export class AppHeaderComponent implements OnInit {
constructor() { }
ngOnInit() { }

}
Empty file.
3 changes: 3 additions & 0 deletions src/app/app-header/app-header.view.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="header">
<h1 class="text-content">Countries & Capitals</h1>
</div>
48 changes: 48 additions & 0 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Component, OnInit, ViewEncapsulation} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS} from 'angular2/router';
import {AppHeaderComponent} from './app-header/app-header.component';
import {AppFooterComponent} from './app-footer/app-footer.component';
import {MainComponent} from './main/main.component';
import {HomeComponent} from './main/home/home.component';
import {CountriesComponent} from './main/countries/countries.component';
import {CountryComponent} from './main/country/country.component';

@Component({
moduleId:'appModule',
selector: 'app',
templateUrl: 'src/app/app.view.html',
styleUrls: ['src/app/app.styles.css'],
directives: [ROUTER_DIRECTIVES,AppHeaderComponent,AppFooterComponent,MainComponent],
providers: [ROUTER_PROVIDERS],
encapsulation: ViewEncapsulation.None
})

// defining routes here
@RouteConfig([
{
path: '/home',
name: 'Home',
component:HomeComponent,
useAsDefault: true
},
{
path: '/countries',
name: 'Countries',
component:CountriesComponent
},
{
path: '/country/:code', // eg localhost:3000/country/US, localhost:3000/country/PK etc
name: 'Country',
component:CountryComponent
}
])


export class AppComponent implements OnInit {
constructor() { }

ngOnInit() {
console.log("app initiated");
}

}
36 changes: 36 additions & 0 deletions src/app/app.styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*GLOBAL STYLES*/

.btn{
border:1px solid grey;
border-radius: 4px;
padding: 4px 10px;
color:black;

}

.text-center{
text-align: center;
}

.lorem{
max-width: 400px;
margin: 40px auto;
}

.btn:hover{
color: white;
background: black;
-webkit-transition: 0.4s all ease;
-moz-transition: 0.4s all ease;
transition: 0.4s all ease;
}
a{
text-decoration: none;
}

/* APP COMPONENT STYLES*/

.header {
text-align:center;
border-bottom:2px solid black;
}
5 changes: 5 additions & 0 deletions src/app/app.view.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div class="main-view-container">
<app-header></app-header>
<main></main>
<app-footer></app-footer>
</div>
33 changes: 33 additions & 0 deletions src/app/countries.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class CountriesService {

constructor (private http: Http) {}
private countriesUrl = 'http://api.geonames.org/searchJSON?q=country&username=ahsan.ubitian'; // URL to web api
private neighboursUrl = "http://api.geonames.org/neighboursJSON?username=ahsan.ubitian&country=";
private countryUrl = "http://api.geonames.org/countryInfoJSON?formatted=true&lang=it&username=ahsan.ubitian&style=full&country=";

getCountries (){
let url = this.countriesUrl; //url to be used for call
return this.http.get(url)
.map(res => res.json())
.map((data) => { return data.geonames; });;
}
getCountry (countryCode){
let url = this.countryUrl + countryCode; //url to be used for call (appending countryCode to make it like '&country=PK')
return this.http.get(url)
.map(res => res.json())
.map((data) => { return data.geonames[0]; }); //since we expect [0] will have our required country
}

getNeighbours(countryCode){
let url = this.neighboursUrl + countryCode; //url to be used for call (appending countryCode to make it like '&country=PK')
return this.http.get(url)
.map(res => res.json())
.map((data) => { return data.geonames; });
}
}
33 changes: 33 additions & 0 deletions src/app/main/countries/countries.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Component, OnInit } from 'angular2/core';
import {ROUTER_DIRECTIVES, Router} from 'angular2/router';
import {CountriesService} from '../../countries.service';
import {SpinnerComponent} from '../../../shared/spinner/spinner.component';
import { HTTP_PROVIDERS } from 'angular2/http';
@Component({
moduleId: 'countriesModule',
selector: 'countries',
templateUrl: 'src/app/main/countries/countries.view.html',
styleUrls:['src/app/main/countries/countries.styles.css'],
directives: [ROUTER_DIRECTIVES,SpinnerComponent],
providers: [CountriesService,HTTP_PROVIDERS]
})
export class CountriesComponent implements OnInit {
private countries = [];
private isRequesting: boolean = true;
constructor(private countriesService: CountriesService, private router:Router) {
//injected countriesService to use it later
}
ngOnInit() {
this.countriesService.getCountries()
.subscribe(countries => {
this.countries = countries;
this.isRequesting = false; //hide loader
});
}

onCountryClick(country){
console.log(country);
this.router.navigate(['Country', {code:country.countryCode}]); //navigate to the desired router
}

}
13 changes: 13 additions & 0 deletions src/app/main/countries/countries.styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#countriesTableContainer{
max-height: 300px;
overflow: auto;
}
#countriesTable{
}
#countriesTable td{
text-align: center;
}
#countriesTable tr:hover{
background-color: #dcdcdc;
cursor: pointer;
}
17 changes: 17 additions & 0 deletions src/app/main/countries/countries.view.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<my-spinner [isRunning]="isRequesting" *ngIf="isRequesting"></my-spinner>
<!--<div *ngIf="!dataLoaded">Loading Countries....</div>-->
<div id="countriesTableContainer" *ngIf="!isRequesting">
<table style="width:100%" id="countriesTable">
<tr>
<th>Name</th>
<th>Country Code</th>
<th>Population</th>
</tr>
<tr *ngFor="let cnt of countries" (click)="onCountryClick(cnt)">
<td>{{cnt.name}}</td>
<td>{{cnt.countryCode}}</td>
<td>{{cnt.population}}</td>
</tr>

</table>
</div>
50 changes: 50 additions & 0 deletions src/app/main/country/country.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Component, OnInit, Pipe, PipeTransform } from 'angular2/core';
import {ROUTER_DIRECTIVES, RouteParams} from 'angular2/router';
import {CountriesService} from '../../countries.service';
import {SpinnerComponent} from '../../../shared/spinner/spinner.component';
import { HTTP_PROVIDERS } from 'angular2/http';

// We use the @Pipe decorator to register the name of the pipe
@Pipe({
name: 'customLimit'
})
// The work of the pipe is handled in the tranform method with our pipe's class
class CustomLimitPipe implements PipeTransform {
transform(array: Array<any>, args: any[]) {
array = array.slice(0,3);
return array;
}
}



@Component({
moduleId: 'countryModule',
selector: 'country',
templateUrl: 'src/app/main/country/country.view.html',
styleUrls:['src/app/main/country/country.styles.css'],
directives: [ROUTER_DIRECTIVES,SpinnerComponent],
providers: [CountriesService,HTTP_PROVIDERS],
pipes:[CustomLimitPipe]
})
export class CountryComponent implements OnInit {
private country = {};
private neighbours = [];
private isRequesting: boolean = true;
constructor(countriesService: CountriesService,params: RouteParams) {
console.log(params);
console.log(params.get("code"));
// get country based on the country code (code) we have
countriesService.getCountry(params.get("code"))
.subscribe(country => {
this.country = country;
// get country neighbours
countriesService.getNeighbours(params.get("code"))
.subscribe(neighbours => {
this.neighbours = neighbours;
this.isRequesting = false; //hide the loader
});
});
}
ngOnInit() { }
}
4 changes: 4 additions & 0 deletions src/app/main/country/country.styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.country-container{
max-width: 300px;
margin: 0 auto;
}
21 changes: 21 additions & 0 deletions src/app/main/country/country.view.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<my-spinner [isRunning]="isRequesting" *ngIf="isRequesting"></my-spinner>
<div class="country-container" *ngIf="!isRequesting">
<div class="country-name">
<h1>{{country.countryName}}</h1>
</div>
<div class="country-info">
<p>Population : {{country.population}}</p>
<p>Area : {{country.areaInSqKm}}</p>
<p>Capital : {{country.capital}}</p>
<p>Population : {{country.population}}</p>

<p *ngIf="neighbours && neighbours.length>0">3 neighbours:
<span *ngFor="let neigh of neighbours|customLimit:3 ; #i=index">
<a [routerLink]="['Country',{code:neigh.countryCode}]">
{{neigh.countryName}}
</a>
<span *ngIf="i<2">,</span>
</span>
</p>
</div>
</div>
14 changes: 14 additions & 0 deletions src/app/main/home/home.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Component, OnInit } from 'angular2/core';
import {ROUTER_DIRECTIVES} from 'angular2/router';
@Component({
moduleId: 'homeModule',
selector: 'home',
templateUrl: 'src/app/main/home/home.view.html',
styleUrls:['src/app/main/home/home.styles.css'],
directives: [ROUTER_DIRECTIVES]
})
export class HomeComponent implements OnInit {
constructor() { }
ngOnInit() { }

}
Empty file.
7 changes: 7 additions & 0 deletions src/app/main/home/home.view.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<div class="home-container">
<div class="inner-container">
<div class="lorem">
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</div>
</div>
</div>
14 changes: 14 additions & 0 deletions src/app/main/main.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Component, OnInit } from 'angular2/core';
import {ROUTER_DIRECTIVES} from 'angular2/router';
@Component({
moduleId: 'mainModule',
selector: 'main',
templateUrl: 'src/app/main/main.view.html',
styleUrls:['src/app/main/main.styles.css'],
directives: [ROUTER_DIRECTIVES]
})
export class MainComponent implements OnInit {
constructor() { }
ngOnInit() { }

}
4 changes: 4 additions & 0 deletions src/app/main/main.styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.main-view-container{
min-height: 150px;
margin: 40px 100px;
}
Loading