Как я могу вызвать метод, созданный / расположенный в родительском компоненте, пока я нахожусь в дочернем компоненте

Я работаю над приложением 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)}`);
        }
      }
    );

Для этого вы можете использовать Subject. Вот простой стек: stackblitz.com/edit/…

Jacopo Sciampi 06.12.2018 15:59

Не слушайте @JacopoSciampi, это плохая практика. Вместо этого слушайте официальная документация.

user4676340 06.12.2018 16:01

Что ж, это не веские причины. Согласно этому: stackoverflow.com/questions/40238549/… это просто другой подход. В следующий раз будьте более конкретными.

Jacopo Sciampi 06.12.2018 16:04

@trichetriche, вы можете привести мне пример, как я могу вызвать метод из родительского компонента? Так что я могу обсудить это здесь с другими людьми

Roxy'Pro 06.12.2018 16:07

@JacopoSciampi Я не говорил, что это плохо, я имел в виду, что это не лучшая практика. если вы посмотрите документ, ваше решение уже есть. Это просто не подходит для этого конкретного случая.

user4676340 06.12.2018 16:13

@ Roxy'Pro Я дал вам документацию. Прочтите, вы будете знать, что делать.

user4676340 06.12.2018 16:14

@trichetriche Я почти закончил, я отправлю свой пример через 5 минут, чтобы мы могли прокомментировать его, если он хороший?

Roxy'Pro 06.12.2018 16:15

Конечно ! Сообщите мне, когда вы его разместите

user4676340 06.12.2018 16:16

@trichetriche проверьте мое решение, пожалуйста, не знал, что это так просто, если это правильный подход, это круто, но я могу решить это также с помощью общих служб? вроде хорошо, теперь давайте вызовем метод из службы getCarSpotsByArea, но это означает, что я должен переместить свой метод в службу ... и это больше работы, чем делать это так: =), и я просто хочу знать, правильный ли это подход и это нормальное решение? Спасибо большое за вашу помощь

Roxy'Pro 06.12.2018 16:27

Думаю, лучшее решение - перенести в сервис. Что, если вам это нужно и в другом месте? Подход правильно состоит в том, чтобы переместить его в службу.

Jimenemex 06.12.2018 16:31

@trichetriche правильный. Вы не должны использовать службу, вы просто перемещаете событие от дочернего к родительскому.

Bogdan Constantinescu 06.12.2018 17:59

@Roxy, первый - плохая практика (он плотно связывает ваши компоненты, поэтому вы не можете их повторно использовать), второй бесполезен (вы можете просто использовать #p для того же эффекта без exportAs). Общие службы отлично подходят для несвязанных компонентов, для связанных компонентов лучше выходы. Суть в том, что все работает отлично, вам просто нужно найти тот, который вам подходит. И поздравляю с тем, что вы их нашли, вы часть 1%, которые действительно учатся, читая более одной страницы документа :)

user4676340 06.12.2018 20:31

@trichetriche Спасибо, приятель, так что в основном мое решение, которое я написал в ответе, довольно хорошее? :)

Roxy'Pro 07.12.2018 08:42

Я бы сказал, что он лучший: D

user4676340 07.12.2018 08:54
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
14
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Что я сделал:

В моем дочернем компоненте я создал свойство, которое будет выдавать нужное мне значение:

@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>

Другие вопросы по теме