我创建了一个CRUD服务,该服务可以调用经典API。我使用行为主题在应用程序的所有组件之间共享数据。问题是,当我执行Crud操作时,并不是所有组件中的数据都实时更新。如果我在其他组件中导航,数据将更新。
我不明白为什么它不能实时运行,也找不到我的错误来源。
如果有人可以帮助我,那将非常好:)
我尝试调用get Candidates()函数,使用组件的每个ngOnInit()中的next()函数更新数据存储,但行为相同
github存储库:https://github.com/jbty/signalr-majority-vote/tree/master/signalR-majority-vote/ClientApp
api角度服务:
export class ApiCandidateService {
public candidatesList: Observable<Candidate[]>;
private baseUrl: string;
private _candidatesList: BehaviorSubject<Candidate[]>;
private dataStore: {
candidatesList: Candidate[];
};
private httpOptions: { headers: HttpHeaders } = {
headers: new HttpHeaders({
"Content-Types": "applications/json"
})
};
public constructor(private http: HttpClient) {
this.baseUrl = "api/Candidates";
this.dataStore = { candidatesList: [] };
this._candidatesList = <BehaviorSubject<Candidate[]>>new BehaviorSubject([]);
this.candidatesList = this._candidatesList.asObservable();
}
public getCandidates() {
this.http.get<Candidate[]>(this.baseUrl, this.httpOptions).subscribe(
(data: Candidate[]) => {
this.dataStore.candidatesList = data;
this._candidatesList.next(Object.assign({}, this.dataStore).candidatesList);
},
error => {
this.handleError(error);
}
);
}
public getCandidate(id: number | string) {
this.http.get<Candidate>(`${this.baseUrl}/${id}`, this.httpOptions).subscribe(
(data: Candidate) => {
let notFound = true;
this.dataStore.candidatesList.forEach((item, index) => {
if (item.candidateId == data.candidateId) {
this.dataStore.candidatesList[index] = data;
notFound = false;
}
});
if (notFound) {
this.dataStore.candidatesList.push(data);
}
this._candidatesList.next(Object.assign({}, this.dataStore).candidatesList);
},
error => {
this.handleError(error);
}
);
}
public createCandidate(newCandidate: Candidate) {
this.http.post<Candidate>(`${this.baseUrl}`, newCandidate, this.httpOptions).subscribe(
(data: Candidate) => {
this.dataStore.candidatesList.push(data);
this._candidatesList.next(Object.assign({}, this.dataStore).candidatesList);
},
error => {
this.handleError(error);
}
);
}
public updateCandidate(id: number | string, updatedCandidate: Candidate) {
this.http.put<Candidate>(`${this.baseUrl}/${id}`, updatedCandidate, this.httpOptions).subscribe(
() => {
this.dataStore.candidatesList.forEach((candidate, i) => {
if (candidate.candidateId == updatedCandidate.candidateId) {
this.dataStore.candidatesList[i] = updatedCandidate;
}
});
this._candidatesList.next(Object.assign({}, this.dataStore).candidatesList);
},
error => {
this.handleError(error);
}
);
}
public deleteCandidate(id: number | string) {
this.http.delete<Candidate>(`${this.baseUrl}/${id}`, this.httpOptions).subscribe(
response => {
this.dataStore.candidatesList.forEach((candidate, i) => {
if (candidate.candidateId == Number(id)) {
this.dataStore.candidatesList.splice(i, 1);
}
});
this._candidatesList.next(Object.assign({}, this.dataStore).candidatesList);
},
error => {
this.handleError(error);
}
);
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error("An error occurred:", error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(`Backend returned code ${error.status}, ` + `body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError("Something bad happened; please try again later.");
}
}
示例组件
export class DeleteCandidatesComponent implements OnInit {
public candidate: Observable<Candidate>;
public candidateId: string;
constructor(
public nav: NavigationService,
private route: ActivatedRoute,
private candidateService: ApiCandidateService
) {
this.candidateId = this.route.snapshot.params.id;
}
public ngOnInit(): void {
this.candidate = this.candidateService.candidatesList.pipe(
map(candidate => candidate.find(item => item.candidateId == Number(this.candidateId)))
);
this.candidateService.getCandidate(this.candidateId);
}
public onDefinitivlyDeleteCandidate(id: string) {
this.candidateService.deleteCandidate(id);
this.nav.outletsNav('classement', 'manage/candidates')
}
}
我的观点
<header>
<h2>
êtes vous sûr de vouloir supprimer définitvement
<strong>{{ (candidate | async)?.firstName }} {{ (candidate | async)?.lastName }}</strong> ?
</h2>
</header>
<aside class="submit">
<button mat-button color="primary" (click)="onDefinitivlyDeleteCandidate(candidateId)">
Oui
</button>
<button mat-button color="warn" (click)="nav.outletsNav('classement', 'manage/candidates')">
annuler
</button>
</aside>
答案 0 :(得分:0)
更新
export class ApiCandidateService {
private baseUrl: string;
private dataStore: {
candidatesList: Candidate[];
};
private _store = new BehaviourSubject<Candidate []>(dataStore);
public state$: this._store.asObservable();
public candidatesList$
private httpOptions: { headers: HttpHeaders } = {
headers: new HttpHeaders({
"Content-Types": "applications/json"
})
};
public constructor(private http: HttpClient) {
this.baseUrl = "api/Candidates";
this.candidatesList$ = this.state$.pipe(map(state =>
state.candidatesList),
distinctUntilChanged());
}
public getCandidates() {
this.http.get<Candidate[]>(this.baseUrl, this.httpOptions).subscribe(
(data: Candidate[]) => {
this.dataStore.candidatesList = data;
this._store.next(Object.assign({},
this.dataStore).candidatesList);
},
error => {
this.handleError(error);
}
);
}
public getCandidate(id: number | string) {
this.http.get<Candidate>(`${this.baseUrl}/${id}`, this.httpOptions).subscribe(
(data: Candidate) => {
let notFound = true;
this.dataStore.candidatesList.forEach((item, index) => {
if (item.candidateId == data.candidateId) {
this.dataStore.candidatesList[index] = data;
notFound = false;
}
});
if (notFound) {
this.dataStore.candidatesList.push(data);
}
this._store.next(Object.assign({}, this.dataStore).candidatesList);
},
error => {
this.handleError(error);
}
);
}
public createCandidate(newCandidate: Candidate) {
this.http.post<Candidate>(`${this.baseUrl}`, newCandidate, this.httpOptions).subscribe(
(data: Candidate) => {
this.dataStore.candidatesList.push(data);
this._store.next(Object.assign({}, this.dataStore).candidatesList);
},
error => {
this.handleError(error);
}
);
}
public updateCandidate(id: number | string, updatedCandidate: Candidate) {
this.http.put<Candidate>(`${this.baseUrl}/${id}`, updatedCandidate, this.httpOptions).subscribe(
() => {
this.dataStore.candidatesList.forEach((candidate, i) => {
if (candidate.candidateId == updatedCandidate.candidateId) {
this.dataStore.candidatesList[i] = updatedCandidate;
}
});
this._store.next(Object.assign({}, this.dataStore).candidatesList);
},
error => {
this.handleError(error);
}
);
}
public deleteCandidate(id: number | string) {
this.http.delete<Candidate>(`${this.baseUrl}/${id}`, this.httpOptions).subscribe(
response => {
this.dataStore.candidatesList.forEach((candidate, i) => {
if (candidate.candidateId == Number(id)) {
this.dataStore.candidatesList.splice(i, 1);
}
});
this._store.next(Object.assign({}, this.dataStore).candidatesList);
},
error => {
this.handleError(error);
}
);
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error("An error occurred:", error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(`Backend returned code ${error.status}, ` + `body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError("Something bad happened; please try again later.");
}
}
在视图组件中
export class DeleteCandidatesComponent implements OnInit {
public candidate: Observable<Candidate>;
public candidateId: string;
constructor(
public nav: NavigationService,
private route: ActivatedRoute,
private candidateService: ApiCandidateService
) {
this.candidateId = this.route.snapshot.params.id;
**this.candidate$ = this.candidateService.candidatesList$.pipe(
map(candidate => candidate.find(item => item.candidateId == Number(this.candidateId)))
);**
}
public ngOnInit(): void {
this.candidateService.getCandidate(this.candidateId);
}
public onDefinitivlyDeleteCandidate(id: string) {
this.candidateService.deleteCandidate(id);
this.nav.outletsNav('classement', 'manage/candidates')
}
}
在模板中
{{ (candidate$ | async)?.firstName }} {{ (candidate$ |
async)?.lastName }}
答案 1 :(得分:0)
您正在更新ngOnInit()
中的属性,只有在导航到该视图时才会调用该属性,因此只有在导航至该组件时才会更新。
您可以创建一个get函数来获取该值并在视图中对其进行更新。
组件:
export class DeleteCandidatesComponent implements OnInit {
public candidate: Observable<Candidate>;
public candidateId: string;
constructor(
public nav: NavigationService,
private route: ActivatedRoute,
private candidateService: ApiCandidateService
) {
this.candidateId = this.route.snapshot.params.id;
}
public ngOnInit(): void {}
public onDefinitivlyDeleteCandidate(id: string) {
this.candidateService.deleteCandidate(id);
this.nav.outletsNav('classement', 'manage/candidates')
}
get getCandidates(): Observable<Candidate>{
this.candidate = this.candidateService.candidatesList.pipe(
map(candidate => candidate.find(item => item.candidateId ==
Number(this.candidateId)))
);
this.candidateService.getCandidate(this.candidateId);
return this.candidate;
}
}
视图:
<header>
<h2>
êtes vous sûr de vouloir supprimer définitvement
<strong>{{ (getCandidates)?.firstName }} {{ (getCandidates)?.lastName }}</strong> ?
</h2>
</header>
<aside class="submit">
<button mat-button color="primary" (click)="onDefinitivlyDeleteCandidate(candidateId)">
Oui
</button>
<button mat-button color="warn" (click)="nav.outletsNav('classement', 'manage/candidates')">
annuler
</button>
</aside>
答案 2 :(得分:0)
问题可能是我的组件不相同。我主要有两个路由器插座,但第二个路由器的数据却无法实时更新
您怎么看?