מדריך 3: httpClient באנגולר - put

מחבר:
בתאריך:

תוכלו למצוא גרסה אנגלית טובה לא פחות של המדריך בכתובת Angular app with PHP backend: part 3 (PUT)

מדריך זה הוא השלישי בסדרת המדריכים שמלמדת כיצד להשתמש ב-httpClient של Angular כדי לתקשר ב-AJAX עם צד השרת של האפליקציה. במדריך זה, נערוך את המידע באמצעות המתודה put.

להורדת קוד האנגולר אותו נפתח במדריך

לחצו כדי לראות את הקוד בפעולה

 

1. ה-service

נוסיף ל-service את המתודה update שקולטת את המידע מהקומפוננטה, ומשדרת אותו לצד השרת באמצעות המתודה put של httpClient.

src/app/car.service.ts

update(car: Car) {
    return this.http.put(`${this.baseUrl}/update`, { data: car });
}
  • המתודה שמשמשת לשידור המידע לצד השרת היא put שמקבלת את נתיב ה-url בתור פרמטר ראשון ואת האובייקט car שמכיל את המידע שהתקבל מהקומפוננטה.
  • המידע שמוחזר מצד השרת כולל מידע ב-header על הצלחת או כישלון הפעולה. את החלק של השרת נקודד לקראת סוף המדריך.

הקוד המלא של ה-service:

src/app/car.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import { map } from 'rxjs/operators';
import { Car } from './car';

@Injectable({
  providedIn: 'root',
})
export class CarService {
  baseUrl = 'http ://localhost/api/';

  constructor(private http : HttpClient) {}

  getAll() {
    return this.http.get(`${this.baseUrl}list`).pipe(
      map((res: any) => {
        return res['data'];
      })
    );
  }

  store(car: Car) {
    return this.http.post(`${this.baseUrl}/store`, { data: car }).pipe(
      map((res: any) => {
        return res['data'];
      })
    );
  }

  update(car: Car) {
    return this.http.put(`${this.baseUrl}/update`, { data: car });
  }
}

 

2. קוד הקומפוננטה

נוסיף לקומפוננטה את המתודה updateCar שקולטת את הערכים שמוזנים לטופס, ונרשמת למתודה update אשר ב-service.

src/app/app.component.ts

updateCar(name: any, price: any, id: any) {
    this.resetAlerts();

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

ההרשמה מתבצעת באמצעות subscribe בגלל שהמתודה update היא observable.

הצפי הוא לאחת משתי אפשרויות של מידע שיוחזר מה- observable:

  • במקרה של שגיאה, נדווח למשתמש על שגיאה שארעה על ידי אכלוס המשתנה error.
  • במקרה של הצלחה, נדווח למשתמש על הצלחת העברת הנתונים באמצעות המשתנה success.

הקוד המלא של הקומפוננטה:

src/app/app.component.ts

import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';

import { Car } from './car';
import { CarService } from './car.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
  cars: Car[] = [];
  car: Car = { model: '', price: 0 };

  error = '';
  success = '';

  constructor(private carService: CarService) {}

  ngOnInit() {
    this.getCars();
  }

  getCars(): void {
    this.carService.getAll().subscribe(
      (data: Car[]) => {
        this.cars = data;
        this.success = 'Success in retrieving the list';
      },
      (err) => {
        this.error = err.message;
      }
    );
  }

  addCar(f: NgForm) {
    this.resetAlerts();

    this.carService.store(this.car).subscribe(
      (res: Car) => {
        // Update the list of cars
        this.cars.push(res);

        // Inform the user
        this.success = 'Created successfully';

        // Reset the form
        f.reset();
      },
      (err) => (this.error = err.message)
    );
  }

  updateCar(name: any, price: any, id: any) {
    this.resetAlerts();

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

  resetAlerts() {
    this.error = '';
    this.success = '';
  }
}

 

3. ה-HTML של הטופס

זוכרים את הרשימה שמציגה את שם המכונית ומחירה (אם אינכם יודעים במה מדובר אז נא להתחיל במדריך הראשון בסדרה על HTTP ו-Angular), את הרשימה הזו נערוך כדי להוסיף יכולות של טופס הכוללות: אפשרות לעריכת המחיר והשם של כל פריט בנפרד. נוסף לכפתור שלחיצה עליו שולחת את המידע הערוך להמשך טיפול בצד הקלאס של הקומפוננטה.

src/app/app.component.html

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

  <div class="container">
    <div *ngFor="let item of cars;let i = index;" class="list-group-item row">
      <div class="col-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-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-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>
  • כל אחד מהפריטים (כל מכונית במערך המכוניות) מודפס בשורה נפרדת של הרשימה.
  • הערכים של השדות קשורים בקשירה דו-כיוונית באמצעות ngModel לפריט ברשימה.
  • לשדות מחיר ושם הצמדתי local reference (ראה הסולמית ב-#model וב-price#).
  • קיימת ולידציה בטופס שמוודאת את תקינות הפרטים לדוגמה האם השם תקין, ובמידה והנתונים אינם תקינים השדה שאינו תקין מקבל קלאס is-invalid, שהוא קלאס של bootstrap, שיצבע את שולי השדה באדום.
  • ניתן ללחוץ על הכפתור רק במידה והנתונים בשדות תקינים אחרת השדה מקבל את ההגדרה disabled.
  • לחיצה על הכפתור מעבירה את המידע לקומפוננטה להמשך טיפול באמצעות המתודה updateCar. כשהמידע שעובר הוא מה-local reference.

 

להורדת קוד האנגולר אותו נפתח במדריך

4. צד השרת

זה קוד ה-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);
  }  
}
  • במקרה של שגיאה מוחזר קוד ממשפחת ה-400.
  • במקרה של הצלחה מוחזר קוד תגובה 204 , שאומר שהפעולה הצליחה אבל ללא החזרת מידע בגוף התגובה (payload).

במדריך הבא נלמד כיצד למחוק פריטים מהרשימה.

במדריך הבא נלמד כיצד למחוק מכוניות מהרשימה.

 

אהבתם? לא אהבתם? דרגו!

0 הצבעות, ממוצע 0 מתוך 5 כוכבים

 

 

הוסף תגובה חדשה

 

= 9 + 6

תמונת המגיב

בנימין בתאריך: 20.01.2021

למה הפרמטר car בתוך סוגריים מסולסלים { data: car }? ואיך בדיוק עובד put?