[英]CRUD using observables without refreshing page
我正在嘗試在 angular 中使用可觀察對象而不在ts
文件中訂閱它們但在html
中使用async
來實現 CRUD。
我的目標是獲取、添加、編輯和刪除從服務器獲取的項目,而無需在每次請求后刷新頁面。
我嘗試用BehaviorSubject
、 ReplaySubject
、 AsyncSubject
來做這件事,並且還尋找材料,但我沒有發現任何有用的東西。
有人可以舉一個例子如何以最好的模式實現這種crud嗎?
下面我粘貼從我之前的嘗試中清除的代碼和從 API 返回的數據結構。
提前致謝。
在documents.service.ts
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DocumentsService {
constructor(private http: HttpClient) { }
getDocuments(): Observable<any[]> {
return this.http.get<any[]>(`https://localhost:5001/docs`)
}
postDocument(item: any): Observable<any> {
return this.http.post<any[]>(`https://localhost:5001/docs`, item)
}
putDocument(id: number, item: any): Observable<any> {
return this.http.put<any[]>(`https://localhost:5001/docs/${id}`, item)
}
deleteDocument(id: number): Observable<any> {
return this.http.delete<any>(`https://localhost:5001/docs/${id}`)
}
}
在documents.component.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { DocumentsService } from 'src/app/services/documents.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent {
documents$: Observable<any> = new Observable()
constructor(private documentsService: DocumentsService) { }
ngOnInit() {
this.getDocuments();
}
getDocuments(): void {
this.documents$ = this.documentsService.getDocuments()
}
postDocument(): void {
this.documentsService.postDocument({
"title": "title",
"description": "lorem ipsum",
"imageUrl": "https://images.pexels.com/photos/2765111/pexels-photo-2765111.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"madeBy": {
"userName": "mike mock",
"email": "mike@mock.com"
}
})
}
putDocument(): void {
this.documentsService.putDocument(4, {
"title": "title",
"description": "lorem ipsum",
"imageUrl": "https://images.pexels.com/photos/2765111/pexels-photo-2765111.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"madeBy": {
"userName": "mike mock",
"email": "mike@mock.com"
}
})
}
deleteDocument(): void {
this.documentsService.deleteDocument(5)
}
}
在documents.component.html
<p routerLink="/">home works!</p>
<button (click)="postDocument()">add me</button>
<button (click)="putDocument()">edit me</button>
<button (click)="deleteDocument()">delete me</button>
<p *ngFor="let document of documents$ | async">
{{ document | json }}
</p>
HTTP 獲取響應:
[
{
"id": 47,
"title": "docker",
"description": "lorem ipsum",
"imageUrl": "https://images.pexels.com/photos/3464632/pexels-photo-3464632.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"madeBy": {
"username": "mike mock",
"email": "mike@mock.com"
}
},
{
"id": 49,
"title": "linux",
"description": "second description",
"imageUrl": "https://images.pexels.com/photos/3900437/pexels-photo-3900437.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"madeBy": {
"username": "mike mock",
"email": "mike@mock.com"
}
}
]
HTTP POST/PUT/DELETE 響應:
{
"id": 50,
"title": "some text",
"description": "lorem ipsum",
"imageUrl": "https://images.pexels.com/photos/2765111/pexels-photo-2765111.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"madeBy": {
"username": "mike mock",
"email": "mike@mock.com"
}
}
Observables 是惰性的,在訂閱之前不會執行。
將您的組件更新為:
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Observable, BehaviorSubject } from 'rxjs';
import { DocumentsService } from 'src/app/services/documents.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent {
documents$: BehaviorSubject<any> = new BehaviorSubject(undefined);
constructor(private documentsService: DocumentsService) { }
ngOnInit() {
this.getDocuments();
}
getDocuments(): void {
this.documentsService.getDocuments().subscribe(this.documents$);
}
postDocument(): void {
this.documentsService.postDocument({
"title": "title",
"description": "lorem ipsum",
"imageUrl": "https://images.pexels.com/photos/2765111/pexels-photo-2765111.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"madeBy": {
"userName": "mike mock",
"email": "mike@mock.com"
}
}).subscribe(_ => this.getDocuments());
}
putDocument(): void {
this.documentsService.putDocument(4, {
"title": "title",
"description": "lorem ipsum",
"imageUrl": "https://images.pexels.com/photos/2765111/pexels-photo-2765111.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"madeBy": {
"userName": "mike mock",
"email": "mike@mock.com"
}
}).subscribe(_ => this.getDocuments());
}
deleteDocument(): void {
this.documentsService.deleteDocument(5).subscribe(_ => this.getDocuments());
}
}
我還強烈建議您強烈輸入 api 並刪除any
.
問題在於您的服務。 在您的服務中,您的 getDocuments() 只是簡單地調用您的后端。 當您在組件中編寫 this.documents$ = this.documentsService.getDocuments() 時,它將調用 function 一次,讀取數據並且以后不再更新。
因此,您需要創建一個主題以將數據存儲在您的服務中,使用 an.asObservable() 使其在外部可用,將您的組件鏈接到該 observable 並在每次 http 調用后更新主題的內容。
像這樣的東西:
export class DocumentsService {
private _documents$ = new BehaviorSubject<Array<Document>>([]);
public documents$: Observable<Array<Document>>;
constructor(private http: HttpClient) {
this.documents$ = this._documents$.asObservable()
}
getDocuments(): Observable<any[]> {
this.http.get<any[]>(`https://localhost:5001/docs`).switchmap(
(response) => this._documents$.next(response)
)
}
postDocument(item: any): Observable<any> {
# update _documents$ here
}
putDocument(id: number, item: any): Observable<any> {
# update _documents$ here
}
deleteDocument(id: number): Observable<any> {
# update _documents$ here
}
}
然后在您的組件中簡單地更新您定義文檔的行
this.documents$ = this.documentsService.documents$
它應該工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.