#angular
#angular
Вопрос:
У меня есть компонент, который отображает список вариантов, которые извлекаются из сервиса, как вы можете видеть здесь.
export class SellingMenuVarietiesComponent implements OnInit {
varieties: Variety[];
constructor(public sellingMenuService: SellingMenuService) { }
ngOnInit(): void {
this.getVarietyList();
}
// Get Variety List
getVarietyList(): void {
this.sellingMenuService.getVarieties().subscribe(res => {
this.varieties = res;
});
}
}
У меня есть другой компонент, который удаляет разновидности, как показано здесь:
export class SellingVarietyEditComponent implements OnInit {
constructor(private sellingMenuService: SellingMenuService) { }
// Remove variety
removeVariety(id: number) {
this.sellingMenuService.removeVariety(id).subscribe(res => {
this.sellingMenuService.getVarieties();
});
}
}
В этом примере оба компонента видны на странице одновременно, поэтому при удалении разнообразия я хочу, чтобы список автоматически обновлялся и отражал это. В настоящее время variety будет успешно удален из базы данных, но останется в списке до тех пор, пока я не обновлю страницу. Обратите внимание, что в removeVariety()
функции из SellingVarietyEditComponent
я повторно вызываю getVarieties()
метод из своего сервиса в попытке обновить список, но это не работает.
Что я делаю не так? Как я могу это сделать?
Вот соответствующие функции из этой службы:
@Injectable()
export class SellingMenuService {
// Get Variety List
public getVarieties(): Observable<any> {
return this.http.get(this.varietyList).map(response => {
return response.json();
}, (error: any) => {
console.log(error);
});
}
// Remove Variety
public removeVariety(varietyId: any): Observable<any> {
return this.http.get(this.removeVarietyUrl varietyId).map(response => {
return response;
}, (error: any) => {
console.log(error);
});
}
}
Редактировать:
Попытка решения EventEmitter:
В SellingMenuService
я добавил этот код (обратите внимание, что я добавил this.updateVarietyList.emit(null);
в getVarieties()
):
@Output() updateVarietyList: EventEmitter<any> = new EventEmitter();
// Get Variety List
public getVarieties(): Observable<any> {
return this.http.get(this.varietyList).map(response => {
this.updateVarietyList.emit(null);
return response.json();
}, (error: any) => {
console.log(error);
// TODO: implement error handling here.
});
}
В SellingVarietyEditComponent
моя кнопка удаления выглядит следующим образом:
<a class="remove-button" (click)="removeVariety(varietyId)" (updateVarietyList)="onVarietyListUpdate($event)" >Remove</a>
И, наконец, в SellingMenuVarietiesComponent
я добавил это:
onVarietyListUpdate() {
console.log('test');
this.getVarietyList();
}
Однако этот код не работает. Я не получаю никаких ошибок, но onVarietyListUpdate()
метод никогда не выполняется. Я вообще на правильном пути? Как я могу это исправить? Найденный мной пример сбивает с толку, и у меня возникают проблемы с применением их к моему коду.
Ответ №1:
Я только что понял, что у вас разные компоненты. Таким образом, решения на самом деле меняются. Но я все еще сохранил старое решение, которое дает вам лучшее представление о том, как справиться с материалом, если вам понадобится в будущем.
НОВОЕ РЕШЕНИЕ
Вы можете создать component-interactions.service.ts, в котором
updateVarieties = new Subject();
updateVarieties$ = this.updateVarieties.asObservable();
getVarieties(){
this.updateVarieties.next();
}
Здесь,
export class SellingMenuVarietiesComponent implements OnInit {
varieties: Variety[];
constructor(private ciService:ComponentInteractionService, public sellingMenuService: SellingMenuService) { }
ngOnInit(): void {
this.ciService.updateVarieties$.subscribe(()=> {
this.getVarieyList();
});
this.getVarietyList();
}
// Get Variety List
getVarietyList(): void {
this.sellingMenuService.getVarieties().subscribe(res => {
this.varieties = res;
});
}
}
В редактируемом компоненте,
export class SellingVarietyEditComponent implements OnInit {
constructor(private ciService:ComponentInteractionService, private sellingMenuService: SellingMenuService) { }
// Remove variety
removeVariety(id: number) {
this.sellingMenuService.removeVariety(id).subscribe(res => {
this.ciService.getVarieties();
});
}
}
СТАРОЕ РЕШЕНИЕ: ЕСЛИ ОДИН КОМПОНЕНТ ОБРАБАТЫВАЕТ РЕДАКТИРОВАНИЕ И ПОКАЗЫВАЕТ
Дело в том, что вам нужно обновить пользовательский интерфейс новыми данными. Один из способов сделать это — вернуть обновленные варианты с ответом об успешном завершении из серверной части после удаления варианта.
Итак, я нажимаю на removeVariety API, выполняю операцию удаления с идентификатором, а вы делаете что-то вроде varieties.GetAll() в серверной части и отправляете обновленные varieties в успешном ответе. И затем вы просто делаете
this.varieties = res;
Для интерфейса это просто сделать.
Другой подход заключается в сохранении идентификатора в переменной, прежде чем вы нажмете на delete API. Теперь у вас есть идентификатор, который вы удаляете, вы нажимаете на API, он успешен, а затем вы делаете
export class SellingVarietyEditComponent implements OnInit {
constructor(private sellingMenuService: SellingMenuService) { }
// Remove variety
removeVariety(id: number) {
let deleteItemId = id;
this.sellingMenuService.removeVariety(id).subscribe(res => {
if(res.status=="SUCCESS"){ /* check if it was successful.(Good practice to include that in API Response*/
this.deleteItemById(deleteItemId);
}
});
}
deleteItemById(id:number){
this.varieties.forEach((value)=> {
if(value.varietyId==id){
let index = this.varieties.indexOf(value);
if(index>-1){
this.varieties.splice(index, 1);
}
}
});
}
Я думаю, что не стоит снова вызывать getVarieties. В вашем коде причина, по которой он не работает, заключается в том, что он возвращает вам наблюдаемое, а вы не подписываетесь на это и не обновляете массив varieties. Если вы все еще хотите вызвать get API. Вы можете сделать
this.getVarietyList();
вместо
this.sellingService.getVarieties();
и снова сделайте эту функцию в компоненте редактирования такой же, как у вас в другом компоненте.
Комментарии:
1. Что мне нужно импортировать, чтобы использовать Subject?
2. Неважно, я использовал import { Subject } из ‘rxjs / Subject’;
3. Сработало ли это? Примите это, если это решение работает для вас!
4. Это сработало, спасибо! Хотя я не совсем понимаю это, не могли бы вы объяснить, как это работает?
5. Итак, вы создаете observable, который публикует данные, на которые вы подписываетесь и получаете данные. Вы вызываете метод, из которого хотите отправить данные, который вызывает next() для отправки этих данных и публикует эти данные, на которые вы подписываетесь и получаете данные. Параметр в next() в идеале содержит данные, но в вашем случае нам не нужен никакой обмен данными. Поэтому в идеале это getVarieties (данные), а затем next (данные). И вы получите эти данные в виде подписки. А затем используйте эти данные.
Ответ №2:
Вы могли бы использовать EventEmitter
в своем SellingMenuService
, чтобы выдавать событие при variety
удалении / обновлении. Прослушайте это событие в SellingMenuVarietiesComponent
и соответствующим образом обновите свой массив
Комментарии:
1. Я попытался это сделать и отредактировал свой пост, чтобы показать свой код. Это не работает, и я не совсем уверен, что я делаю неправильно.