Hey in the previous post we covered saving the expense details to the database, in this post we will cover updating the expense details. We will continue with the same example which we created in the previous post. Let’s begin…
We will cover the following topics
- Create rest endpoint to get the single expense
- We will make HTTP GET request from an angular application
- We will update the expense details
First, let’s start with creating rest endpoint in spring boot application – inside the ExpenseService.java
declare a method to get a single expense object.
Open, ExpenseService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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); } |
ExpenseServiceImpl.java
class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
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; } } |
ExpenseController.java
Open, ExpenseController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
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); } } |
Now the rest endpoint is working as we expected, let’s move on to the front end part, and make HTTP GET request from the angular application. let’s begin…
Open, expense.service.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
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) ) } } |
add-expense.component.ts
Open, add-expense.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
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"); } ) } } |
routerLink
inside the list-expense.component.html
for the individual expense, to call /editexpense/:id
route
Open, list-expense.component.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<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> </div> |
When the user clicks on any of the expense records, control navigate to the add-expense.component.html in which all the details are auto-filled inside the form –
That’s it now if the user makes any changes/updates to the record, and when they click add expense button that will automatically update the record.
How does it happen? Well, when the user clicks the add expense button, control navigates to the component, from there it will call service method, saveExpense()
inside we will make an HTTP POST request to spring boot application. So now the spring boot calls the JpaRepository save()
method. This save()
works in both ways, meaning if the id available then it will update the record, if the id is not available then it will create new record.
You can find the Github repository here
You can find the step by step video series here