Я работаю над приложением Angular, это в основном небольшое приложение, которое отображает места для автомобилей, машины могут находиться в разных регионах (например, в гараже, вне гаража).
И когда я нажимаю на пятно, оно меняет цвет на красный, как будто оно снято, но я не вижу его, пока не закрою окно и не вернусь снова.
Вот 2 компонента,
один cars-spot-list является родительским компонентом, а сам car-spot является дочерним компонентом, поскольку он является частью списка.
Итак, что я хочу сделать, это когда я нажимаю на место для машины, я обновляю свою базу данных, поскольку это место занято, и я хотел бы снова вызвать свой метод getCarSpotsByArea (), но он находится в parent-component,
Итак, мой вопрос: как я могу вызвать родительский метод из дочернего компонента?
Я мог бы переместить его на service, но мне бы хотелось этого избежать.
Вот как это выглядит:
Мой код:
Когда я нажимаю на компонент ребенокcar-spot, например Spot 1, происходит следующее:
onClick(carSpot: CarSpot) {
this._carSpotService.changeCarSpotState(carSpot).subscribe(
// Successful responses call the first callback.
() => {
// CALL AGAIN SOMEHOW METHOD FROM A PARENT TO REFRESH MY VIEW
// for example: getCarSpotsByArea(carSpot.areaId);
},
(err: HttpErrorResponse) => {
if (err.error instanceof Error) {
console.info('An error occurred:', err.error.message);
} else {
console.info(`Backend returned code ${err.status}, body was: ${err.error}`);
}
}
);
};
}
Компонент Родитель: компонент car-spot-list
getCarSpotsByArea(areaId: string) {
this._carSpotService.getCarSpotsByAreaId(areaId)
.subscribe(
data => {
this.carSpots = data;
},
// Errors will call this callback instead:
(err: HttpErrorResponse) => {
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
console.info('An error occurred:', err.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.info(`Backend returned code ${err.status}, body was: ${JSON.stringify(err.error)}`);
}
}
);
Не слушайте @JacopoSciampi, это плохая практика. Вместо этого слушайте официальная документация.
Что ж, это не веские причины. Согласно этому: stackoverflow.com/questions/40238549/… это просто другой подход. В следующий раз будьте более конкретными.
@trichetriche, вы можете привести мне пример, как я могу вызвать метод из родительского компонента? Так что я могу обсудить это здесь с другими людьми
@JacopoSciampi Я не говорил, что это плохо, я имел в виду, что это не лучшая практика. если вы посмотрите документ, ваше решение уже есть. Это просто не подходит для этого конкретного случая.
@ Roxy'Pro Я дал вам документацию. Прочтите, вы будете знать, что делать.
@trichetriche Я почти закончил, я отправлю свой пример через 5 минут, чтобы мы могли прокомментировать его, если он хороший?
Конечно ! Сообщите мне, когда вы его разместите
@trichetriche проверьте мое решение, пожалуйста, не знал, что это так просто, если это правильный подход, это круто, но я могу решить это также с помощью общих служб? вроде хорошо, теперь давайте вызовем метод из службы getCarSpotsByArea, но это означает, что я должен переместить свой метод в службу ... и это больше работы, чем делать это так: =), и я просто хочу знать, правильный ли это подход и это нормальное решение? Спасибо большое за вашу помощь
Думаю, лучшее решение - перенести в сервис. Что, если вам это нужно и в другом месте? Подход правильно состоит в том, чтобы переместить его в службу.
@trichetriche правильный. Вы не должны использовать службу, вы просто перемещаете событие от дочернего к родительскому.
@Roxy, первый - плохая практика (он плотно связывает ваши компоненты, поэтому вы не можете их повторно использовать), второй бесполезен (вы можете просто использовать #p для того же эффекта без exportAs). Общие службы отлично подходят для несвязанных компонентов, для связанных компонентов лучше выходы. Суть в том, что все работает отлично, вам просто нужно найти тот, который вам подходит. И поздравляю с тем, что вы их нашли, вы часть 1%, которые действительно учатся, читая более одной страницы документа :)
@trichetriche Спасибо, приятель, так что в основном мое решение, которое я написал в ответе, довольно хорошее? :)
Я бы сказал, что он лучший: D



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Что я сделал:
В моем дочернем компоненте я создал свойство, которое будет выдавать нужное мне значение:
@Output() onUpdateCarSpot = new EventEmitter<string>();
onClick(carSpot: CarSpot) {
this._carSpotService.changeCarSpotState(carSpot).subscribe(
// Successful responses call the first callback.
() => {
// Here is the place where I needed to call parent method so here
// on success callback I've emitted value
this.onUpdateCarSpot(carSpot.areaId);
},
(err: HttpErrorResponse) => {
if (err.error instanceof Error) {
console.info('An error occurred:', err.error.message);
} else {
console.info(`Backend returned code ${err.status}, body was: ${err.error}`);
}
}
);
};
}
А в родительском компоненте car-spot-list.component.html я сделал следующее (является частью):
<car-spot (onUpdateCarSpot) = "getCarSpotsByArea($event)"></car-spot>
Я добавил (onUpdateCarSpot), который фактически является именем моего эмиттера событий Output из моего дочернего компонента, и я просто сказал:
Хорошо, когда я что-то испускаю (это выполняется обратным вызовом в дочернем компоненте), вызываю метод под названием getCarSpotsByArea, и я передал / испускал areaId, потому что мой родительский метод getCarSpotsByArea принимает и areaId в качестве аргумента, и все!
В дополнение к EventEmitter, как упомянуто выше, есть 2 других способа вызвать родительский компонент из дочерних компонентов.
1) Вставить родительский компонент в дочерний компонент
export class ChildComponent {
constructor(private parent: ParentComponent) {
}
callParentMethod() {
this.parent.methodHandler();
}
}
2) Если у вас есть контроль над ParentComponent, вы можете использовать exportAs:
@Component({
...
exportAs: 'parent'
})
export class ParentComponent {
...
}
export class ChildComponent {
@Input() handler: Function;
...
callParentMethod() {
this.handler();
}
}
В Html вы можете ссылаться на него как на:
<parent #p = "parent">
<child [handler] = "p.methodHandler"></child>
</parent>
Для этого вы можете использовать
Subject. Вот простой стек: stackblitz.com/edit/…