Hey everyone, in the previous post we discussed updating the expense details, and in this post, we will discuss deleting an expense. we can delete expense from two different places, one is in the list expense page, where each expense contains the delete button/link and another place inside the add expense page while editing the expense. Let’s add this to both the places…
We will cover the following topics –
- First, we will create a rest endpoint to delete an expense
- Next, we will make delete request to rest endpoint from angular application
First, let’s declare a new method inside the ExpenseService.java
to delete an expense
package in.bushansirgur.expensetracker.service; import java.util.List; import in.bushansirgur.expensetracker.model.Expense; public interface ExpenseService { List<Expense> findAll(); Expense save(Expense expense); Expense findById(Long id); void delete(Long id); }
Now let’s provide an implementation for deleting an expense inside the ExpenseServiceImpl.java
package in.bushansirgur.expensetracker.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import in.bushansirgur.expensetracker.model.Expense; import in.bushansirgur.expensetracker.repository.ExpenseRepository; @Service public class ExpenseSerivceImpl implements ExpenseService { @Autowired ExpenseRepository expenseRepository; @Override public List<Expense> findAll() { return expenseRepository.findAll(); } @Override public Expense save(Expense expense) { expenseRepository.save(expense); return expense; } @Override public Expense findById(Long id) { if(expenseRepository.findById(id).isPresent()){ return expenseRepository.findById(id).get(); } return null; } @Override public void delete(Long id) { Expense expense = findById(id); expenseRepository.delete(expense); } }
Now we have a service method for deleting an expense, all we need to do is call this service method inside the ExpenseController.java
package in.bushansirgur.expensetracker.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import in.bushansirgur.expensetracker.model.Expense; import in.bushansirgur.expensetracker.service.ExpenseService; @CrossOrigin("*") @RestController @RequestMapping("/api/v1") public class ExpenseController { @Autowired ExpenseService expenseService; @GetMapping("/expenses") public ResponseEntity<List<Expense>> get() { List<Expense> expenses = expenseService.findAll(); return new ResponseEntity<List<Expense>>(expenses, HttpStatus.OK); } @PostMapping("/expenses") public ResponseEntity<Expense> save(@RequestBody Expense expense) { Expense expenseOne = expenseService.save(expense); return new ResponseEntity<Expense>(expenseOne, HttpStatus.OK); } @GetMapping("/expenses/{id}") public ResponseEntity<Expense> get(@PathVariable("id") Long id) { Expense expense = expenseService.findById(id); return new ResponseEntity<Expense>(expense, HttpStatus.OK); } @DeleteMapping("/expenses/{id}") public ResponseEntity<String> delete(@PathVariable("id") Long id) { expenseService.delete(id); return new ResponseEntity<String>("Expense is deleted successfully.!", HttpStatus.OK); } }
Alright, now we have a rest endpoint to delete an expense, all we need to do is test our work –
Now let’s move on to the front end part – let’s utilize this rest endpoint to make HTTP delete request for deleting an expense
Open expense.service.ts
, add the following code –
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { Expense } from '../models/expense'; @Injectable({ providedIn: 'root' }) export class ExpenseService { private getUrl: string = "http://localhost:8080/api/v1/expenses"; constructor(private _httpClient: HttpClient) { } getExpenses(): Observable<Expense[]> { return this._httpClient.get<Expense[]>(this.getUrl).pipe( map(response => response) ) } saveExpense(expense: Expense): Observable<Expense> { return this._httpClient.post<Expense>(this.getUrl, expense); } getExpense(id: number): Observable<Expense> { return this._httpClient.get<Expense>(`${this.getUrl}/${id}`).pipe( map(response => response) ) } deleteExpense(id: number): Observable<any> { return this._httpClient.delete(`${this.getUrl}/${id}`, {responseType: 'text'}); } }
Now let’s call this service method inside the component, so as we discussed earlier we will delete expense from 2 different places, first let’s add inside the list expenses page.
Open list-expenses.component.ts
, add the following code
import { Component, OnInit } from '@angular/core'; import { Expense } from 'src/app/models/expense'; import { ExpenseService } from 'src/app/services/expense.service'; @Component({ selector: 'app-list-expenses', templateUrl: './list-expenses.component.html', styleUrls: ['./list-expenses.component.css'] }) export class ListExpensesComponent implements OnInit { expenses: Expense[] = []; constructor(private _expenseService: ExpenseService) { } ngOnInit(): void { this.listExpenses(); } deleteExpense(id: number) { this._expenseService.deleteExpense(id).subscribe( data => { console.log('deleted response', data); this.listExpenses(); } ) } listExpenses() { this._expenseService.getExpenses().subscribe( data => this.expenses = data ) } }
Now, let’s add delete button/link inside the list-expenses.component.html
view template
<div class="row"> <div class="col-md-4"> <a class="btn btn-primary text-light" routerLink="/addexpense">Add Expense</a> </div> </div> <div> <div class="card mt-1" *ngFor="let expense of expenses"> <a routerLink="/editexpense/{{expense.id}}" class="card-body flex"> <span class="text-capitalize font-weight-bold">{{expense.expense}}</span> <span class="float-right mr-2 badge badge-pill badge-warning font-weight-bold amount">{{expense.amount | currency: 'INR'}}</span> </a> <div class="card-footer"> <button class="btn btn-danger" (click)="deleteExpense(expense.id)" style="width: 10%;">Delete</button> </div> </div> </div>
At this, if you run the application, you will see the following output –
Now let’s add the same functionality inside the add-expense.component.ts
file
import { Component, OnInit } from '@angular/core'; import { Expense } from 'src/app/models/expense'; import { ExpenseService } from 'src/app/services/expense.service'; import { Router, ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-add-expense', templateUrl: './add-expense.component.html', styleUrls: ['./add-expense.component.css'] }) export class AddExpenseComponent implements OnInit { expense: Expense = new Expense(); constructor(private _expenseService: ExpenseService, private _router: Router, private _activatedRoute: ActivatedRoute) { } ngOnInit(): void { const isIdPresent = this._activatedRoute.snapshot.paramMap.has('id'); if (isIdPresent) { const id = +this._activatedRoute.snapshot.paramMap.get('id'); this._expenseService.getExpense(id).subscribe( data => this.expense = data ) } } saveExpense() { this._expenseService.saveExpense(this.expense).subscribe( data => { console.log('response', data); this._router.navigateByUrl("/expenses"); } ) } deleteExpense(id: number) { this._expenseService.deleteExpense(id).subscribe( data => { console.log('deleted response', data); this._router.navigateByUrl('/expenses'); } ) } }
Now we need to add the delete button/link inside the add-expense.component.html
view template
<div class="container"> <div class="row"> <form (ngSubmit)="saveExpense()"> <div class="form-group"> <input type="text" name="expense" [(ngModel)]="expense.expense" placeholder="Enter expense name" class="form-control col-md-12 "/> </div> <div class="form-group"> <input type="text" name="amount" [(ngModel)]="expense.amount" placeholder="Enter amount" class="form-control col-md-12" /> </div> <div class="form-group"> <textarea type="text" name="description" [(ngModel)]="expense.description" placeholder="Enter description" class="form-control col-md-12"></textarea> </div> <button type="submit" class="btn btn-primary">Add Expense</button> <button *ngIf="expense.id" (click)="deleteExpense(expense.id)" class="btn btn-danger">Delete</button> </form> </div> </div>
At this point, if you run the application, you will see the following output –
That’s it for this post, in the next post we will look at the search operation.
You can find the Github repository here
You can find the step by step video series here