Federico Zacayan

Software Devloper.

Angular

Install the Angular CLI

npm install -g @angular/cli

Create a project

ng new angular-tutorial

Say "no routing"

Would you like to add Angular routing? (y/N)

Choose "CSS"

❯ CSS
  SCSS   [ https://sass-lang.com/documentation/syntax#scss                ]
  Sass   [ https://sass-lang.com/documentation/syntax#the-indented-syntax ]
  Less   [ http://lesscss.org                                             ]
  Stylus [ http://stylus-lang.com                                         ] 

Go to the project folder

cd angular-tutorial

Run the local server

ng serve -o

Create a service named Api

ng generate service Api

Import the service ApiService created in src/app/app.modules.js and add it as a provider.

...
import { ApiService } from './api.service';
...
@NgModule({
  ...
  providers: [ApiService],
  ...
})

Import HttpClient in src/app/api.service.js

...
import { HttpClient }    from '@angular/common/http';

Import the module HttpClientModule in src/app/app.modules.js

...
import { HttpClientModule }    from '@angular/common/http';
...
@NgModule({
  ...
  imports: [
    ...
    HttpClientModule
  ],
  ...
})

Create a private attribute in the constructor method in src/app/app.modules.js and a new method named getUsers.

constructor(private http: HttpClient ) { }

getUsers(){
    return this.http.get('https://jsonplaceholder.typicode.com/users/');
}

The method get of the object HttpClient return an observable object. This observable is waiting for an asynchronous response.

When the answer arrive, it execute one or several callback functions. These callbacks are created calling the subscribe method.

We will do it in the component src/app/app.component.js, but first, we have to import the service.

import { ApiService } from './api.service';

We need a property which contain the data to be rendered into the template.

contacts:any = [];

We create a private attribute which will contain the service.

constructor(private api: ApiService) { }

And finally, implement the method ngOnInit with the subscribe method from the observable mentioned before. In this way we creating our own callback function.

ngOnInit() {
    this.api.getUsers()
    .subscribe(data => {
        this.contacts = data;
        console.log(data)
    });
}

Now, we are ready to implement our template in src/app/app.component.html

<div *ngFor="let contact of contacts">
    <span>Name: {{contact.name}}</span><br/>
    <span>Email: {{contact.email}}</span><br/>
    <span>Phone: {{contact.phone}}</span>
    <hr/>
</div>

You can test the application now.

To delete a user we need to add a buttom in the template src/app/app.component.html.

<input type="button" (click)="drop(contact.id)" value="Delete"/>

We have to implement drop method in the component src/app/app.component.js.

...
deleting = (id) =>{
    let tmp  = this.contacts.filter((a) => {
        return a.id !== id;
    })
    this.contacts = tmp;
}

drop = (id) => {
    this.api.deleteUsers(id)
    .subscribe(data => {
        this.deleting(id)
    });
}
...

When the property this.contacts is updated the template is rendered again automatically.

We need to implement the request deleteUser method into the service in src/app/api.service.js

...
deleteUsers(id){
    return this.http.delete('https://jsonplaceholder.typicode.com/users/'+id);
}
...

You can test deleting functionality now.

For update we will avoid UX requirements and we will make it easy using the attribute named contenteditable.

We also will set id (template reference) to some elements of template adding the sign # which is something that angular allow us to do.

They are #name, #email and #phone and we used them as first parameter in update methods.

<div *ngFor="let contact of contacts">
    <span>Name: <span contenteditable="true"
    #name (blur)='update(name, "name", contact)'>{{contact.name}}</span></span><br/>
    <span>Email: <span contenteditable="true"
    #mail (blur)='update(mail, "mail", contact)'>{{contact.email}}</span></span><br/>
    <span>Phone: <span contenteditable="true"
    #phone (blur)='update(phone, "phone", contact)'>{{contact.phone}}</span></span>
    <input type="button" (click)="drop(contact.id)" value="Delete"/>
    <hr/>
</div>

Then, we have to implement the update method in the component src/app/app.component.js.

...
update = (element, field, post) => {
    post[field] = element.innerHTML;
    this.api.updateUser(post)
    .subscribe(data => {
        console.log(data)
    });
}
...

We can receive directly the value instead of element.innerHTML, but in this way you can realize that here element is and DOM object.

Now, in the service (src/app/api.service.js) we need to import HttpHeaders class to add headers to our http request.

import { HttpClient, HttpHeaders } from '@angular/common/http';

And Implement the request into updateUser method.

...
httpOptions = {
    headers: new HttpHeaders({ 'Content-Type': 'application/json; charset=UTF-8' })
};

updateUser(post) {
    return this.http.put(
        'https://jsonplaceholder.typicode.com/posts/'+post.id,
        post,
        this.httpOptions
    );
}
...

You can test update functionality now.

Finally, we implement create method adding it in a bottom of the template.

<input type="button" (click)='create()' value="Create new  User"/>

We need to implement the cerate method in the component src/app/app.component.js.

...
create = () => {
    console.log('creating');
    this.api.createUser({
            name: 'Jhon Doe',
            email: 'bar@email.com',
            phone: '444-555'
        })
    .subscribe(data => {
        console.log(data)
        this.contacts.push(data);
    });
}
...

We need to implement the createUser method in the serive src/app/api.service.js.

We assume we already set up the property this.httpOptions in previous steps.

...
createUser(post) {
    return this.http.post(
        'https://jsonplaceholder.typicode.com/posts/',
        post,
        this.httpOptions
    );
}
...

You can test create functionality now.

Final code you have to have is the following:

src/app/app.module.ts

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

import { AppComponent } from './app.component';
import { ApiService } from './api.service';
import { HttpClientModule }    from '@angular/common/http';

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

src/app/app.component.ts

import { Component } from '@angular/core';
import { ApiService } from './api.service';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})

export class AppComponent {

    title = 'angular-tutorial';
    contacts:any = [];

    constructor(private api: ApiService) { }

    deleting = (id) =>{
        let tmp  = this.contacts.filter((a) => {
            return a.id !== id;
        })
        this.contacts = tmp;
    }

    drop = (id) => {
        this.api.deleteUsers(id)
        .subscribe(data => {
            this.deleting(id)
        });
    }

    update = (element, field, post) => {
        post[field] = element.innerHTML;
        this.api.updateUser(post)
        .subscribe(data => {
            console.log(data)
        });
    }

    create = () => {
        console.log('creating');
        this.api.createUser({
                name: 'Jhon Doe',
                email: 'bar@email.com',
                phone: '444-555'
            })
        .subscribe(data => {
            console.log(data)
            this.contacts.push(data);
        });
    }

    ngOnInit() {
        this.api.getUsers()
        .subscribe(data => {
            this.contacts = data;
            console.log(data)
        });
    }
}

src/app/app.component.html

<div *ngFor="let contact of contacts">
    <span>Name: <span contenteditable="true"
    #name (blur)='update(name, "name", contact)'>{{contact.name}}</span></span><br/>
    <span>Email: <span contenteditable="true"
    #mail (blur)='update(mail, "mail", contact)'>{{contact.email}}</span></span><br/>
    <span>Phone: <span contenteditable="true"
    #phone (blur)='update(phone, "phone", contact)'>{{contact.phone}}</span></span>
    <input type="button" (click)="drop(contact.id)" value="Delete"/>
    <hr/>
</div>
<input type="button" (click)='create()' value="Create new  User"/>