Make a simple App

Using Angular 2 ? X

Requirements

  • Node installation (node 6.9.0 or higher https://nodejs.org/)
  • Browser (ex: Chrome)
  • IDE (ex : Atom, intelliJ, VSCode...etc)

Configurations

install angular cli

#npm install -g @angular/cli

create a new project 

#ng new simple-app

build it

#ng build

run it

#ng serve

go to the app directory

#cd simple-app

Open your browser at :
 http://localhost:4200

Exploring
Angular Boiler plate

DEMO

Make our first component

create a new component

#ng generate component article
create src/app/article/article.component.html (26 bytes)
create src/app/article/article.component.spec.ts (635 bytes)
create src/app/article/article.component.ts (273 bytes)
create src/app/article/article.component.css (0 bytes)
update src/app/app.module.ts (402 bytes)

result :

check it all

  • *.component.html => template
  • *.component.css => style
  • *.component.spec.ts => test file
  • *.component.ts => logic file
  • app.module.ts => register our component

article

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-article',
  templateUrl: './article.component.html',
  styleUrls: ['./article.component.css']
})
export class ArticleComponent implements OnInit {
    
  readonly title: string;
  readonly content: string;

  constructor(){
    this.title = 'First Article';
    this.content = 'Hello World';
  }

  ngOnInit(): void {
  }

}

an article should have a title and a content

add this to your article.component.ts

<div>
    <h3> {{this.title}} </h3>
    <p> {{this.content}} </p>
</div>

add something inside your article.component.html

call it in the app.component.html (clean it before)

<app-article></app-article>

Do not need to rebuild !
It refresh automatically

try to add an authors to article...

add some css !

Component Input

Let's create a new component
that will display all articles

#ng generate component articles

1 - Call it in app.component.html instead of app-article

2 - Add a call of app-article inside articles.component.html

change fields to input parameters in article.component.ts

1 - in article change title and content field 

    @Input()
    title : string;
    @Input("customContent")
    content : string;

(remove initalization inside constructor)

2 - now app-article take two input parameters

<app-article [title]="'MyTitle'" [customContent]="'MyContent'"></app-article>

add a new field in articles component

article = {title: 'My First Article', content : 'Hello World'};

use it in articles.component.html

<app-article [title]="this.article.title" [customContent]="this.article.content"></app-article>
  • Change parameter to an article object
  • Try to add other article
  • In articles we should have a list of articles...

Tricks :

  • create an Article interface or class
  • *ngFor

Make our first service

git clone https://github.com/Amirault/angular5-articles-app.git 
git reset --hard 8f525c70354dee5509bd480f7bbccc218263ced3
cd angular5-articles-app
npm install

Backup

Create a new service

#ng generate service article

Now we have

import { Injectable } from '@angular/core';

@Injectable()
export class ArticleService {

  constructor() { }

}

Article service should give  all Articles

create a new method inside article.service.ts

public getArticles() : Article[] {
    return [{
      title: 'My First Article',
      content: 'Hello World',
      author: 'Orangefire'
    }, {
      title: 'Angular component',
      content: 'Angular component looks awesome!',
      author: 'Orangefire'
    }, {
      title: 'Angular service',
      content: 'I read something about angular service, i will try it soon',
      author: 'Orangefire'
    }];
} 

Now we can use it to retrieve all articles from our "Articles" component

constructor(private articleService: ArticleService) {
}

Then inject it in articles.component.ts constructor

Finally call it to get all articles ! (use it in html)

articles(): Article[] {
    return this.articleService.getArticles();
}
  providers: [ArticleService]

First register it to app.module.ts

Backup

git reset --hard 0b050a6d9d01f198a3732bb747997520cda4dffe

Connect it to real world

npm install -g json-server

install json-server ( our backend server )

create your database in a file named db.json

{
"articles" : [{
      "title": "My First Article",
      "content": "Hello World",
      "author": "Orangefire"
    }, {
      "title": "Angular component",
      "content": "Angular component looks awesome!",
      "author": "Orangefire"
    }, {
      "title": "Angular service",
      "content": "I read something about angular service, i will try it soon",
      "author": "Orangefire"
    }]
}

Start it

json-server --watch db.json

https://github.com/typicode/json-server

add HttpClient in order to make http request

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {HttpClientModule} from '@angular/common/http';

import { AppComponent } from './app.component';
import { ArticleComponent } from './article/article.component';
import { ArticlesComponent } from './articles/articles.component';
import {ArticleService} from "./services/article.service";


@NgModule({
  declarations: [
    AppComponent,
    ArticleComponent,
    ArticlesComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [ArticleService],
  bootstrap: [AppComponent]
})
export class AppModule { }

HTTPClient

Calling our backend with httpClient
in Article.service.ts

in article.service.ts import HttpClient and Observable

constructor(private http : HttpClient) {
}
import {HttpClient} from "@angular/common/http";
import {Observable} from "rxjs/Observable";

inject HttpClient

make a call to get our Articles from our backend

  public getArticles(): Observable<Article[]> {
    return this.http.get<Article[]>("http://localhost:3000/articles");
  }

We are providing a reactive stream on Articles !

Subscribing in our articles component 

  • Register our obervable on ngOnInit

  • provide an observable to the view (html)

export class ArticlesComponent implements OnInit {

  articles: Observable<Article[]>;

  constructor(private articleService: ArticleService) {
  }

  ngOnInit() {
    this.articles = this.articleService.getArticles();
  }

}

use "| async" (async pipe) to subscribe on the view

<app-article *ngFor="let article of this.articles() | async" [article]="article">
</app-article>

Test It !

  • Remove | async and use the providing ".subscribe()" method
     
  • Add an "id" field to Article
     
  • Implement delete service wich permit to remove an Article

    Tricks :
  • DELETE /articles/{id}
  • Use "(click)" event

Component
Output

git reset --hard 27e273f1d8cae3c9f05ac0eb445dfcae68756981

Backup

An article can be deleted

provide a delete button on article

<button (click)="delete()"></button>

then create the associated function of click event

On click the article component
should push a delete notification

EventEmitter

Create an output field in our article.component

@Output()
deletedArticle : EventEmitter<Article> = new EventEmitter();
delete(){
    this.deletedArticle.emit(this.article);
}

when the delete button is clicked then emit the deletedArticle

Now our component exposes an event

<app-article  [article]="article" (deletedArticle)="delete($event)"></app-article>

we can subscribe to the event 

delete($event) will be executed on (deletedArticle) event

On articles.component.html

use the new event 

implement delete fonction in articles.component.ts

prototype : delete(article : article)

Make a Form

git reset --hard b3ff04ba037a2912b1879c3e5d73b188d5867390

Backup

create a new component

$ng generate component article-creation

Import reactive form in app.module

import { ReactiveFormsModule } from '@angular/forms';
imports: [
    BrowserModule,
    HttpClientModule,
    ReactiveFormsModule 
  ],

Create a form

in article-create.component.ts initialize form

  articleForm : FormGroup;

  constructor(private fb: FormBuilder) {
    this.articleForm = this.fb.group({
      title: ['Fake Title', Validators.required ],
      content : ['', Validators.required ],
      authors : ['', Validators.required ],
    });
  }
import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms';

Create a form

in article-create.component.html make your  form

<h2>Article</h2>
<h3><i>Create your article</i></h3>
<form [formGroup]="articleForm" (ngSubmit)="createArticle()">
  <div class="form-group">
    <label class="center-block">title:
      <input class="form-control" formControlName="title">
    </label>
    <br />
    <label class="center-block">content:
      <textarea class="form-control" formControlName="content"></textarea>
    </label>
    <br />
    <label class="center-block">authors:
      <input class="form-control" formControlName="authors">
    </label>
    <br />
    <button class="btn btn-success" [disabled]="articleForm.invalid" type="submit">Save</button>
  </div>
</form>

Submit new article

  • Use (ngSubmit) to recieve input data 
  • Create the new article into our database
  • Refresh articles list ...
const { title, content, authors } = this.articleForm.value;
const newArticle = {
  title,
  content,
  authors
}

unwrapping formGroup, example : 

 Service, HTTP POST, no id, EventEmitter ?

Tricks : 

Navigation / ROUTE

git reset --hard 36f30626172039325429121711dfc09a0c0dab6d

Backup

App component

Articles
component

Article Creation
Component 

/

Currently

App component

Articles
component

Article Creation
Component 

/create

/articles

/

With Routing

Default

Configurations 

import { RouterModule, Routes } from '@angular/router';
imports: [
    RouterModule.forRoot(
      appRoutes,
      { enableTracing: true } // <-- debugging purposes only
    ),
    BrowserModule,
    HttpClientModule,
    ReactiveFormsModule
  ],

In our app.module

Enable Routing

const appRoutes: Routes = [
  { path: 'create', component: ArticleCreationComponent },
  { path: 'articles', component: ArticlesComponent },
  { path: '', component: ArticlesComponent }
]

in our app.module configure each route

  • when calling /create show ArticleCreationComponent

  • when calling /articles show ArticlesComponent

  • when calling / show Articles Component

in app.component.html replace all by

<router-outlet></router-outlet>

it enable routing on app component

Enable Routing

Test it !

Use routerLink

provide routing to "/create"

<a routerLink="/create" >New Article</a>
  • Use a nav-bar

  • We should navigate to articles component

  • Bonus : Dynamic route
    • On articles component, when clicking on article name go to the corresponding article using routing (only the corresponding article must be showed).

Angular.io Doc

#5 courses-angular-simple-app

By orangefire

#5 courses-angular-simple-app

  • 597