Django + Angular 6 example | Django Rest Framework + MySQL CRUD example – Part 3: Angular Client

django-angular-6-django-rest-api-mysql-angular-django-project-structure-feature-image

This tutorial is part 3 of Django-Angular-MySQL series. Today, we will create Angular Client to make HTTP request & receive response from Django Server.

>> Part 1: Overview
>> Part 2: Django Server

Video

Angular Client Overview

Goal

The image below shows overview about Angular Components that we will create:

django-angular-6-django-rest-api-mysql-angular-client-architecture

Project Structure

django-angular-6-django-rest-api-mysql-angular-project-structure

We have:
– 4 components: customers-list, customer-details, create-customer, search-customer.
– 3 modules: FormsModule, HttpClientModule, AppRoutingModule.
customer.ts: class Customer (id, firstName, lastName)
customer.service.ts: Service for Http Client methods
app-routing.module.ts: Routing configuration

Setup Angular Project

Create Angular Project

Run command: ng new AngularDjango.

Create Service & Components

On Project folder, run commands below:
ng g s customer
ng g c create-customer
ng g c customer-details
ng g c customers-list
ng g c search-customers
On each Component selector, delete app- prefix, then change tslint.json rules"component-selector" to false.

Implement Angular Client App

Data Model

Create new file named customer.ts:

export class Customer {
    id: number;
    name: string;
    age: number;
    active: boolean;
}

Data Service

customer.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class CustomerService {

  private baseUrl = 'http://localhost:8000/customers';

  constructor(private http: HttpClient) { }

  getCustomer(id: number): Observable<object width="300" height="150"> {
    return this.http.get(`${this.baseUrl}/${id}`);
  }

  createCustomer(customer: Object): Observable<object> {
    return this.http.post(`${this.baseUrl}/`, customer);
  }

  updateCustomer(id: number, value: any): Observable<object> {
    return this.http.put(`${this.baseUrl}/${id}`, value);
  }

  deleteCustomer(id: number): Observable<any> {
    return this.http.delete(`${this.baseUrl}/${id}`);
  }

  getCustomersList(): Observable<any> {
    return this.http.get(`${this.baseUrl}/`);
  }

  getCustomersByAge(age: number): Observable<any> {
    return this.http.get(`${this.baseUrl}/age/${age}/`);
  }

  deleteAll(): Observable<any> {
    return this.http.delete(`${this.baseUrl}/`);
  }
}

Components

Customer Details

customer-details/customer-details.component.ts


import { Component, OnInit, Input } from '@angular/core';
import { CustomerService } from '../customer.service';
import { Customer } from '../customer';

import { CustomersListComponent } from '../customers-list/customers-list.component';

@Component({
  selector: 'customer-details',
  templateUrl: './customer-details.component.html',
  styleUrls: ['./customer-details.component.css']
})
export class CustomerDetailsComponent implements OnInit {

  @Input() customer: Customer;

  constructor(private customerService: CustomerService, private listComponent: CustomersListComponent) { }

  ngOnInit() {
  }

  updateActive(isActive: boolean) {
    this.customerService.updateCustomer(this.customer.id,
      { name: this.customer.name, age: this.customer.age, active: isActive })
      .subscribe(
        data => {
          console.log(data);
          this.customer = data as Customer;
        },
        error => console.log(error));
  }

  deleteCustomer() {
    this.customerService.deleteCustomer(this.customer.id)
      .subscribe(
        data => {
          console.log(data);
          this.listComponent.reloadData();
        },
        error => console.log(error));
  }

}

customer-details/customer-details.component.html

<div *ngIf="customer">
  <div>
    <label>Name: </label> {{customer.name}}
  </div>
  <div>
    <label>Age: </label> {{customer.age}}
  </div>
  <div>
    <label>Active: </label> {{customer.active}}
  </div>

  <span class="button is-small btn-primary" *ngIf='customer.active' (click)='updateActive(false)'>Inactive</span>

  <span class="button is-small btn-primary" *ngIf='!customer.active' (click)='updateActive(true)'>Active</span>

  <span class="button is-small btn-danger" (click)='deleteCustomer()'>Delete</span>

  <hr />
</div>

List of Customers

customers-list/customers-list.component.ts


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

import { CustomerService } from '../customer.service';
import { Customer } from '../customer';

@Component({
  selector: 'customers-list',
  templateUrl: './customers-list.component.html',
  styleUrls: ['./customers-list.component.css']
})
export class CustomersListComponent implements OnInit {

  customers: Observable;

  constructor(private customerService: CustomerService) { }

  ngOnInit() {
    this.reloadData();
  }

  deleteCustomers() {
    this.customerService.deleteAll()
      .subscribe(
        data => {
          console.log(data);
          this.reloadData();
        },
        error => console.log('ERROR: ' + error));
  }

  reloadData() {
    this.customers = this.customerService.getCustomersList();
  }

}

customers-list/customers-list.component.html

<h1>Customers</h1>

<div *ngFor="let customer of customers | async" style="width: 300px;">
  <customer-details [customer]='customer'></customer-details>
</div>

<div>
  <button type="button" class="button btn-danger" (click)='deleteCustomers()'>Delete All</button>
</div>

Create Customer

create-customer/create-customer.component.ts


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

import { Customer } from '../customer';
import { CustomerService } from '../customer.service';

@Component({
  selector: 'create-customer',
  templateUrl: './create-customer.component.html',
  styleUrls: ['./create-customer.component.css']
})
export class CreateCustomerComponent implements OnInit {

  customer: Customer = new Customer();
  submitted = false;

  constructor(private customerService: CustomerService) { }

  ngOnInit() {
  }

  newCustomer(): void {
    this.submitted = false;
    this.customer = new Customer();
  }

  save() {
    this.customerService.createCustomer(this.customer)
      .subscribe(
        data => {
          console.log(data);
          this.submitted = true;
        },
        error => console.log(error));
    this.customer = new Customer();
  }

  onSubmit() {
    this.save();
  }

}

create-customer/create-customer.component.html

<h3>Create Customer</h3>
<div [hidden]="submitted" style="width: 300px;">
  <form (ngSubmit)="onSubmit()">
    <div class="form-group">
      <label for="name">Name</label>
      <input type="text" class="form-control" id="name" required [(ngModel)]="customer.name" name="name">
    </div>

    <div class="form-group">
      <label for="age">Age</label>
      <input type="text" class="form-control" id="age" required [(ngModel)]="customer.age" name="age">
    </div>

    <button type="submit" class="btn btn-success">Submit</button>
  </form>
</div>

<div [hidden]="!submitted">
  <h4>You submitted successfully!</h4>
  <button class="btn btn-success" (click)="newCustomer()">Add</button>
</div>

Search Customers

search-customers/search-customers.component.ts


import { Component, OnInit } from '@angular/core';
import { Customer } from '../customer';
import { CustomerService } from '../customer.service';

@Component({
  selector: 'search-customers',
  templateUrl: './search-customers.component.html',
  styleUrls: ['./search-customers.component.css']
})
export class SearchCustomersComponent implements OnInit {

  age: number;
  customers: Customer[];

  constructor(private dataService: CustomerService) { }

  ngOnInit() {
    this.age = 0;
  }

  private searchCustomers() {
    this.customers = [];
    this.dataService.getCustomersByAge(this.age)
      .subscribe(customers => this.customers = customers);
  }

  onSubmit() {
    this.searchCustomers();
  }

}

search-customers/search-customers.component.html

<h3>Find By Age</h3>
<div style="width: 300px;">
  
<div class="form-group">
      <label for="lastname">Age</label>
      <input type="text" class="form-control" id="age" required="" ngmodel="" age="" name="age">
</div>

<div class="btn-group">
      <button type="submit" class="btn btn-success">Submit</button>
</div>
  
</div>
<ul>
 	<li ngfor="let customer of customers">
<h4>{{customer.id}} - {{customer.name}} {{customer.age}}</h4>
</li>
</ul>
Add Router

app-routing.module.ts


import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CustomersListComponent } from './customers-list/customers-list.component';
import { CreateCustomerComponent } from './create-customer/create-customer.component';
import { SearchCustomersComponent } from './search-customers/search-customers.component';

const routes: Routes = [
    { path: '', redirectTo: 'customer', pathMatch: 'full' },
    { path: 'customer', component: CustomersListComponent },
    { path: 'add', component: CreateCustomerComponent },
    { path: 'findbyage', component: SearchCustomersComponent },
];

@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]
})

export class AppRoutingModule { }

And AppComponent HTML for routing:app.component.html

<div style="padding: 20px;">
<h1 style="color: blue;">ozenero.com</h1>
<h3>Angular - Django App</h3>
  <nav>
    <a routerlink="customer" class="btn btn-primary active" role="button" routerlinkactive="active">Customers</a>
    <a routerlink="add" class="btn btn-primary active" role="button" routerlinkactive="active">Add</a>
    <a routerlink="findbyage" class="btn btn-primary active" role="button" routerlinkactive="active">Search</a>
  </nav>
  <router-outlet></router-outlet>
</div>

App Module

app.module.ts


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

import { AppComponent } from './app.component';
import { CreateCustomerComponent } from './create-customer/create-customer.component';
import { CustomerDetailsComponent } from './customer-details/customer-details.component';
import { CustomersListComponent } from './customers-list/customers-list.component';
import { SearchCustomersComponent } from './search-customers/search-customers.component';

import { AppRoutingModule } from './app-routing.module';

@NgModule({
  declarations: [
    AppComponent,
    CreateCustomerComponent,
    CustomerDetailsComponent,
    CustomersListComponent,
    SearchCustomersComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Run & Check Results

– Run Django server with command: python manage.py runserver.
– Run Angular App with command: ng serve.

– Open browser for url http://localhost:4200/:

Add Customer:

django-angular-6-example-django-rest-api-mysql-angular-add-customer

Show Customers:

django-angular-6-django-rest-api-mysql-angular-show-customers

Click on Active button to update Customer status:

django-angular-6-example-django-rest-api-mysql-angular-update-customers

Search Customers by Age:

django-angular-6-example-django-rest-api-mysql-angular-search-customers

Delete a Customer:

django-angular-6-example-django-rest-api-mysql-angular-delete-customer

Delete All Customers:

django-angular-6-example-django-rest-api-mysql-angular-delete-all-customers

Source Code

Angular-Django-MySQL-example-Angular-Rest-Client

6 thoughts on “Django + Angular 6 example | Django Rest Framework + MySQL CRUD example – Part 3: Angular Client”

  1. I am so happy to read this. This is the kind of manual that needs to be given and not the random misinformation that is at the other blogs. Appreciate your sharing this greatest doc.

Leave a Reply

Your email address will not be published. Required fields are marked *