Blog postAngular app with PHP backend: part 3 (PUT)

Learn to code Angular app with PHP backend: part 3 (PUT)

Published August 16, 2018

This is the third tutorial in the series about coding an Angular app with a PHP backend. In the previous tutorial, we posted a new car to the backend so it can be stored in the database. In this one, we will edit the data using the HttpClientModule's put() method.

Demo for the Angular and PHP tutorial

All of the tutorials in the series about developing Angular and PHP application:

  1. How to install Angular?
  2. What is REST API? In plain English
  3. What is Angular Observable?
  4. Angular app with PHP backend: part 1 (GET)
  5. Angular app with PHP backend: part 2 (POST)
  6. Angular app with PHP backend: part 3 (PUT)
  7. Angular app with PHP backend: part 4 (DELETE)

Click to see the code in action

You can dowload the source code from the conclusion section

# 1. The HTML form

Remember the list that shows the name and price of the car (if it doesn't ring a bell, then start with the first tutorial in the series). We will add editing capabilities to the form, including an option to update the price and name of each item separately. In addition to a button, that once clicked sends the data for further handling in the component's class.

Replace the content of the list with the following code:

src/app/app.component.html

<div id="theList">
  <h2>The list</h2>

  <div class="list-group">
    <div *ngFor="let item of cars;let i = index;" class="list-group-item row">
      <div class="col-md-4">
        <input type="text"
               [(ngModel)]="cars[i].model"
               class="form-control"
               required
               pattern="^[a-zA-Z]+$"
               #model="ngModel"
               [ngClass]="{ 'is-invalid': model.touched && model.invalid }">
      </div>
      <div class="col-md-4">
        <input type="number"
               [(ngModel)]="cars[i].price"
               class="form-control"
               required
               #price="ngModel"
               [ngClass]="{ 'is-invalid': price.touched && price.invalid }">
      </div>
      <div class="col-md-4">
        <input type="button"
               value="Update"
               class="btn btn-success btn-sm"
               [disabled]="model.invalid || price.invalid"
               (click)="updateCar(model, price, item.id)">
      </div>
    </div>
  </div>
</div>
  • Angular prints each item (car) to a separate line of the list.
  • The values of the form fields have a two-way binding to the Car object in the component with the help of ngModel.
  • The model and price fields have local references (#model, #price).
  • I have attached validation rules to the fields, so if the data in the field is not valid, the field gets the "is-invalid" CSS class.
  • You can submit the form only if it is valid. Unless it is valid, the update button is disabled.
  • Pushing the "update" button passes the data to the component with the updateCar() method.

# 2. The code for the component

Add the updateCar() method to the component. The method gets the values from the form and subscribes to the update() method in the service.

src/app/app.component.ts

updateCar(name, price, id) {
    this.success = '';
    this.error = '';

    this.carService.update({ model: name.value, price: price.value, id: +id })
      .subscribe(
        (res) => {
          this.cars    = res;
          this.success = 'Updated successfully';
        },
        (err) => this.error = err
      );
}

The method updateCar() needs to subscribe to the update() method which is an observable, and so the update() method returns one of two results:

  1. In the case of an error, the method will expose an error message to the user.
  2. In the case of success, the method will update the local list of cars with the one that comes back from the service.

# 3. The service

Now you need to add the update() method to the service. The method receives the data from the component before sending it to the PHP backend with the HttpClientModule's put() method.

src/app/car.service.ts

update(car: Car): Observable<Car[]> {
    return this.http.put(`${this.baseUrl}/update`, { data: car })
      .pipe(map((res) => {
        const theCar = this.cars.find((item) => {
          return +item['id'] === +car['id'];
        });
        if (theCar) {
          theCar['price'] = +car['price'];
          theCar['model'] = car['model'];
        }
        return this.cars;
      }),
      catchError(this.handleError));
}

The httpClientModule's put() method accepts the URL as the first parameter and the data (car object) as the second.

The server side (as you'll see in the following section) returns only success or error codes in the response header.

In the case of success, the update() method needs to return the updated list of cars. For this, I used the find method on the list of cars to search for the car that needs to be updated, before updating it with the data entered by the user.

As usual, the handleError method handles the errors.

# 4. The server side

The following PHP code is responsible for updating the database on the server side of the app:

api/update.php

<?php
require 'connect.php';

// Get the posted data.
$postdata = file_get_contents("php://input");

if(isset($postdata) && !empty($postdata))
{
  // Extract the data.
  $request = json_decode($postdata);
	
  // Validate.
  if ((int)$request->data->id < 1 || trim($request->data->model) == '' || (int)$request->data->price < 1) {
    return http_response_code(400);
  }
    
  // Sanitize.
  $id    = mysqli_real_escape_string($con, (int)$request->data->id);
  $model = mysqli_real_escape_string($con, trim($request->data->model));
  $price = mysqli_real_escape_string($con, (int)$request->data->price);

  // Update.
  $sql = "UPDATE `cars` SET `model`='$model',`price`='$price' WHERE `id` = '{$id}' LIMIT 1";

  if(mysqli_query($con, $sql))
  {
    http_response_code(204);
  }
  else
  {
    return http_response_code(422);
  }  
}

In case of error, the code returns a response code from the 400 family (you can read the tutorial about status codes and the REST API).

In the case of success, a response code 204 is returned, which indicates that the operation was successful but no data is returned in the response body.

# Conclusion

Now, that you know how to update records with the httpClient's put() method you are ready for the next tutorial. In the following tutorial, you'll learn how to delete list items.

Click to download the source code for the tutorials

comments powered by Disqus