How To Develop Angular 17 CRUD App using a REST API

How To Develop Angular 17 CRUD App using a REST API

Avatar photoPosted by

Hi there, today we will be developing an Angular 17 CRUD app using a REST API. The four basic operations in any programming are CRUD. CRUD is an acronym for CREATE, READ, UPDATE, DELETE.

Angular is a popular open-source front-end web application framework primarily maintained by Google and a community of developers. It’s used for building dynamic, single-page web applications (SPAs) and provides tools and architecture to streamline the development process. Angular enables developers to create rich, interactive, and responsive user interfaces.

In this tutorial, we will be using the REST API available that is made by Binaryboxtus. you can check it out here.

Prerequisite:

  • ^18.13.0 || ^20.9.0
  • @angular/cli

Step 1: Create An Angular 17 Project

First, select a folder that you want the Angular 17 project to be created then execute this command on Terminal or CMD :

ng new angular-crud-app --routing --no-standalone

Step 2: Install packages

After creating a fresh angular project, go to the Angular 17 project folder and install these packages:

  • bootstrap – a package of bootstrap framework
  • sweetalert2 – a package for pop-up boxes
  • axios – a promised-based HTTP library that is used to request to a server or API.
npm i bootstrap
npm i sweetalert2
npm i axios

After installing the packages. import the bootstrap in style.css.

src\styles.css

/* You can add global styles to this file, and also import other style files */
@import "~bootstrap/dist/css/bootstrap.css";

Step 3: Configure Application Environment

After installing the packages, we will now generate the app environment. We will declare the API base URL and API Key. Run the command below:

ng generate environments

You can get the API_KEY here. Click the “Reveal Key” button and copy the API key.

image 21 Binaryboxtuts

After running the command this will generate files for the environment. let’s add value to the environment.

environment.development.ts

export const environment = {
    production: false,
    apiUrl: 'https://mock-api.binaryboxtuts.com/',
    apiKey: 'insert_api_key_here'
};

After configuring the environment, let’s configure the axios on main.ts.

src\main.ts

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import axios from 'axios';
import { environment } from './environments/environment.development';


axios.defaults.baseURL = environment.apiUrl
 
axios.interceptors.request.use(function (config) {
  config.headers['X-Binarybox-Api-Key'] = environment.apiKey
  return config;
});

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));


Step 4: Create Components

We will now create the components. run the command below:

ng generate component project/index
ng generate component project/create
ng generate component project/show
ng generate component project/edit

after running these commands it will create folders with files in them. We will now update the code on it.

src\app\project\create\create.component.ts

import { Component } from '@angular/core';
import { ProjectService } from '../project.service';
import Swal from 'sweetalert2'

@Component({
  selector: 'app-create',
  templateUrl: './create.component.html',
  styleUrls: ['./create.component.css']
})
export class CreateComponent {
  name:string = ''
  description:string = ''
  isSaving:boolean = false

  constructor(public projectService: ProjectService) {}

  handleSave(){
    this.isSaving = true
    this.projectService.create({name:this.name, description:this.description})
    .then(({data}) => {
      this.isSaving = false
      Swal.fire({
        icon: 'success',
        title: 'Project saved successfully!',
        showConfirmButton: false,
        timer: 1500
      })
      this.name = ""
      this.description = ""
      return data

    }).catch(error => {
      this.isSaving = false
      Swal.fire({
        icon: 'error',
        title: 'An Error Occured!',
        showConfirmButton: false,
        timer: 1500
      })
      return error
    })
  }
  

}

src\app\project\create\create.component.html

<h2 class="text-center mt-5 mb-3">Create New Project</h2>
<div class="card">
    <div class="card-header">
        <a routerLink="/project/index"
            class="btn btn-outline-info float-right"
            >View All Projects
        </a>
    </div>
    <div class="card-body">
        <form >
            <div class="form-group">
                <label html="name">Name</label>
                <input 
                    [(ngModel)]="name"
                    type="text"
                    class="form-control"
                    id="name"
                    name="name"/>
            </div>
            <div class="form-group">
                <label html="description">Description</label>
                <textarea 
                    [(ngModel)]="description"
                    class="form-control"
                    id="description"
                    rows="3"
                    name="description"></textarea>
            </div>
            <button 
                [disabled]="isSaving"
                (click)="handleSave()"
                type="button"
                class="btn btn-outline-primary mt-3">
                Save Project
            </button>
        </form>
    </div>
</div>

src\app\project\edit\edit.component.ts

import { Component, OnInit } from '@angular/core';
import { ProjectService } from '../project.service';
import { ActivatedRoute } from '@angular/router';
import Swal from 'sweetalert2'
import { Project } from '../project';

@Component({
  selector: 'app-edit',
  templateUrl: './edit.component.html',
  styleUrls: ['./edit.component.css']
})
export class EditComponent implements OnInit {
  project:Project
  isSaving:boolean = false

  constructor(public projectService: ProjectService, private route: ActivatedRoute) {
    this.project = {
      id:this.route.snapshot.params['id'],
      name: '',
      description: ''
    }
  }

  ngOnInit(): void {
    this.projectService.show(this.route.snapshot.params['id']).then(({data}) => {
      this.project = data
    }).catch(error => {return error})
    
  }

  handleSave(){
    this.isSaving = true
    this.projectService.update(this.project)
    .then(({data}) => {
      this.isSaving = false
      Swal.fire({
        icon: 'success',
        title: 'Project saved successfully!',
        showConfirmButton: false,
        timer: 1500
      })
      return data

    }).catch(error => {
      this.isSaving = false
      Swal.fire({
        icon: 'error',
        title: 'An Error Occured!',
        showConfirmButton: false,
        timer: 1500
      })
      return error
    })
  }
}

src\app\project\edit\edit.component.html

<h2 class="text-center mt-5 mb-3">Edit Project</h2>
<div class="card">
    <div class="card-header">
        <a routerLink="/project/index"
            class="btn btn-outline-info float-right"
            >View All Projects
        </a>
    </div>
    <div class="card-body">
        <form >
            <div class="form-group">
                <label html="name">Name</label>
                <input 
                    [(ngModel)]="project.name"
                    type="text"
                    class="form-control"
                    id="name"
                    name="name"/>
            </div>
            <div class="form-group">
                <label html="description">Description</label>
                <textarea 
                    [(ngModel)]="project.description"
                    class="form-control"
                    id="description"
                    rows="3"
                    name="description"></textarea>
            </div>
            <button 
                [disabled]="isSaving"
                (click)="handleSave()"
                type="button"
                class="btn btn-outline-primary mt-3">
                Save Project
            </button>
        </form>
    </div>
</div>

src\app\project\index\index.component.ts

import { Component, OnInit } from '@angular/core';
import { ProjectService } from '../project.service';
import { Project } from '../project';
import Swal from 'sweetalert2'

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

  projects: Project[] = [];

  constructor(public projectService: ProjectService) { }

  ngOnInit(): void {
    this.fetchProjectList()
  }

  fetchProjectList(){
    this.projectService.getAll().then(({data}) => {
      this.projects = data;
    }).catch(error => {return error})
  }

  handleDelete(id:number){
    Swal.fire({
      title: 'Are you sure?',
      text: "You won't be able to revert this!",
      icon: 'warning',
      showCancelButton: true,
      confirmButtonColor: '#3085d6',
      cancelButtonColor: '#d33',
      confirmButtonText: 'Yes, delete it!'
    }).then(result =>{
      if (result.isConfirmed) {

        this.projectService.delete(id)
        .then( response => {
          Swal.fire({
            icon: 'success',
            title: 'Project deleted successfully!',
            showConfirmButton: false,
            timer: 1500
          })
          this.fetchProjectList()
          return response
        }).catch(error => {
          Swal.fire({
            icon: 'error',
           title: 'An Error Occured!',
           showConfirmButton: false,
           timer: 1500
          })
          return error
        })

      }
    })  
  }

}

src\app\project\index\index.component.html

<div class="container">
    <h2 class="text-center mt-5 mb-3">Project Manager</h2>
    <div class="card">
        <div class="card-header">
            <a routerLink="/project/create"
                class="btn btn-outline-primary float-right"
                >Create New Project
            </a>
        </div>
        <div class="card-body">
     
            <table class="table table-bordered">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Description</th>
                        <th width="240px">Action</th>
                    </tr>
                </thead>
                <tbody>
                     
                    <tr *ngFor="let project of projects" >
                        <td>{{ project.name }}</td>
                        <td>{{ project.description }}</td>
                        <td>
                            <a [routerLink]="['/project', project.id, 'show']" class="btn btn-outline-info mx-1">Show</a>
                            <a [routerLink]="['/project', project.id, 'edit']" class="btn btn-outline-success mx-1">Edit</a>
                            <button 
                                (click)="handleDelete(project.id)"
                                class="btn btn-outline-danger mx-1">
                                Delete
                            </button>
                        </td>
                    </tr>
                         
                </tbody>
            </table>
        </div>
    </div>
</div>

src\app\project\show\show.component.ts

import { Component, OnInit } from '@angular/core';
import { ProjectService } from '../project.service';
import { ActivatedRoute } from '@angular/router';
import { Project } from '../project';

@Component({
  selector: 'app-show',
  templateUrl: './show.component.html',
  styleUrls: ['./show.component.css']
})
export class ShowComponent implements OnInit {
  project:Project

  constructor(public projectService: ProjectService, private route: ActivatedRoute) {
    this.project = {
      id:this.route.snapshot.params['id'],
      name: '',
      description: ''
    }
  }

  ngOnInit(): void {
    this.projectService.show(this.route.snapshot.params['id']).then(({data}) => {
      this.project = data
    }).catch(error => {return error})
    
  }
}

src\app\project\show\show.component.html

<h2 class="text-center mt-5 mb-3">Show Project</h2>
<div class="card">
    <div class="card-header">
        <a routerLink="/project/index"
            class="btn btn-outline-info float-right"
            >View All Projects
        </a>
    </div>
    <div class="card-body">
        <b className="text-muted">Name:</b>
        <p>{{project.name}}</p>
        <b className="text-muted">Description:</b>
        <p>{{project.description}}</p>
    </div>
</div>

Step 5: Create Module and Routing

After creating the component we will then create a module and routing. Run the command below:

ng generate module project --routing

now we will update the code of the module and routing.

src\app\project\project.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ProjectRoutingModule } from './project-routing.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { IndexComponent } from './index/index.component';
import { CreateComponent } from './create/create.component';
import { EditComponent } from './edit/edit.component';
import { ShowComponent } from './show/show.component';


@NgModule({
  declarations: [
    IndexComponent,
    CreateComponent,
    EditComponent,
    ShowComponent
  ],
  imports: [
    CommonModule,
    ProjectRoutingModule,
    FormsModule,
    ReactiveFormsModule
  ]
})
export class ProjectModule { }

src\app\project\project-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { IndexComponent } from './index/index.component';
import { CreateComponent } from './create/create.component';
import { EditComponent } from './edit/edit.component';
import { ShowComponent } from './show/show.component';

const routes: Routes = [
  { path: '', redirectTo: 'project/index', pathMatch: 'full'},
  { path: 'project', redirectTo: 'project/index', pathMatch: 'full'},
  { path: 'project/index', component: IndexComponent },
  { path: 'project/:id/show', component: ShowComponent },
  { path: 'project/create', component: CreateComponent },
  { path: 'project/:id/edit', component: EditComponent } 
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class ProjectRoutingModule { }

Step 6: Create Services and Interface

We will now create the services and interface

ng generate service project/project
ng generate interface project/project

Let’s update the code of services and interface.

src\app\project\project.service.ts

import { Injectable } from '@angular/core';
import axios from 'axios';
import { Project } from './project';

@Injectable({
  providedIn: 'root'
})

export class ProjectService {

  getAll (): Promise<any>{
    return axios.get('/api/projects')
  }

  delete (id:number): Promise<any>{
    return axios.delete('/api/projects/' + id)
  }

  create(data:any): Promise<any>{
    let payload = {
      name: data.name,
      description: data.description
    }

    return axios.post('/api/projects', payload)
  }

  show (id:number): Promise<any>{
    return axios.get('/api/projects/' + id)
  }

  update(data:Project): Promise<any>{
    let payload = {
      name: data.name,
      description: data.description
    }

    return axios.patch('/api/projects/' + data.id, payload)
  }

}

src\app\project\project.ts

export interface Project {
    id: number;
    name: string;
    description: string;
}

Step 7: Update the AppModule and AppComponent

After finishing the step above we will now update the app module and app component:

src\app\app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ProjectModule } from './project/project.module';

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

src\app\app.component.html

<div class="container">
<router-outlet></router-outlet>
</div>

Step 8: Run the app

We’re all done, what is left is to run the app.

ng serve

Open this URL:

http://localhost:4200/

Screenshots:

Index Page

How To Develop ReactJS CRUD App using a REST API

Create Page

How To Develop ReactJS CRUD App using a REST API

Edit Page

How To Develop ReactJS CRUD App using a REST API

Show Page

How To Develop ReactJS CRUD App using a REST API