מדריך 3: httpClient באנגולר - put
תוכלו למצוא גרסה אנגלית טובה לא פחות של המדריך בכתובת Angular app with PHP backend: part 3 (PUT)
מדריך זה הוא השלישי בסדרת המדריכים שמלמדת כיצד להשתמש ב-httpClient של Angular כדי לתקשר ב-AJAX עם צד השרת של האפליקציה. במדריך זה, נערוך את המידע באמצעות המתודה put.
להורדת קוד האנגולר אותו נפתח במדריך
מדריכים נוספים בסדרת httpClient
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 כוכבים
בנימין בתאריך: 20.01.2021
למה הפרמטר car בתוך סוגריים מסולסלים { data: car }? ואיך בדיוק עובד put?