Angular CRUD 4: Update

This is the fourth in a series of posts on performing CRUD operations in Angular and it’s focus will be on adding the ability to update a villain.

As with the previous posts in this series I will describe the code that is required for performing the update which means not every step to get a working example is shown here. The complete solution can be found on GitHub.

The core components

Create a new service called villainTransferService. This service will be responsible for passing data between the existing list-villains component and the new update-villains component.

import { Injectable } from '@angular/core';
import { Villain } from '../classes/villain';

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

  private villain: Villain;

  constructor() { }

  setVillain(villain: Villain) {
    this.villain = villain;
  }

  getVillain() {
    const tempVillain = this.villain;
    this.clearVillain();
    return tempVillain;
  }

  clearVillain() {
    this.villain = undefined;
  }
}

The edit button has been added to each villain by the following change to the list-villains.component.html

<tr>
  <th scope="row">{{ villain.id }}</th>
  <td  class="w-25 p-3">{{ villain.name }}</td>
  <td  class="w-25 p-3">{{ villain.episode }}</td>
  <td><button type="button" class="btn btn-primary" (click)="toUpdateVillain(villain.id, villain.name, villain.episode)">Edit</button></td>
</tr>

The button calls a new method called toUpdateVillain on list-villains.component.ts passing to it the id, name and episode of the row selected

toUpdateVillain(id: string, name: string, episode: string ) {      
    const villain = { id: +id, name: name, episode: episode };
    this.villainTransferService.setVillain(villain);
    this.router.navigateByUrl("/updatevillain");
  }

The method creates a villain object using the incoming parameters. The object is then passed to the setVillain method from the villainTransferService.

At this point the processing moves to the new component update-villain. In order to get there a new route is required. When /updatevillain is entered in the url the UpdateVillainComponent is invoked. This is reflected in the following addition to app-routing.module.ts:

...
{ path: "updatevillain", component: UpdateVillainComponent },
...

The update-villain component encapsulates the Update functionality. It’s template contains a form that will display the record which is to be changed.

When the component is created, the ngOnit life cycle hook runs. This retrieves the villain object from the villainTransferService and uses it to populate the form field values.

ngOnInit() {        
    const villain = this.villainTransferService.getVillain();
    this.updateVillainForm.setValue({
      id: villain.id,
      name: villain.name,
      episode: villain.episode,
});

Once changes have been made, the update button invokes the updateVillain() method which is defined in the update-villain.component.ts:

updateVillain() {

    if (this.updateVillainForm.valid) {      
      // get the id and convert to a number
      const idstr = this.updateVillainForm.get('id').value;
      const id = +idstr;

      const name = this.updateVillainForm.get('name').value;
      const episode = this.updateVillainForm.get('episode').value;
      
      const villain = { id, name, episode };

      this.villainSubscription = this.villainService.updateVillain(villain).subscribe();

      this.router.navigateByUrl("/");
    }
  }

This method obtains the values from form and uses them to create a villain object. This object is then passed to the updateVillain method of villainService and the final step is to navigate back to the list of villains component.

Bug

During testing I found an interesting bug. If you create a new villain and then try to edit her or him the result will be a duplicate record is created rather than the existing record being updated. The issue is up on GitHub.

What’s next?

The final part of this series will be on the D in CRUD, Delete.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.