Токен впрыска не сбрасывается при изменении компонента - PullRequest
0 голосов
/ 16 февраля 2020

Я не уверен в мелких деталях, поэтому, возможно, это даже не сработает, но, похоже, для этого должно быть какое-то решение. У меня есть родительский компонент, который использует два дочерних компонента на вкладках, например:

<div class="container" *ngIf="page === 'tab1'">
    <refresher-component></refresher-component>
    <child-component1></child-component1>
</div>
<div class="container" *ngIf="page === 'tab2'">
    <refresher-component></refresher-component>
    <child-component2></child-component2>
</div>

Родитель также имеет компонент обновления, который отвечает за обновление данных на обеих вкладках. Каждый из дочерних компонентов внедряет службу, которая реализует интерфейс Refreshable:

  • Дочерний компонент 1: constructor(private service1: Service1)
  • Дочерний компонент 2: constructor(private service2: Service2)

Каждый сервис выглядит следующим образом (замените 1 на 2 для 2-го сервиса):

@Injectable()
export class Service1 implements Refreshable<Type1[]>

refersher-component выглядит следующим образом:

public constructor(@Inject(RefresherServiceToken) public refreshableService: Refreshable<any>) {
    console.log('refreshable', this.refreshableService);
}

Что происходит, когда я загружаю страница (1-я вкладка по умолчанию), console.log выводит Service1. Однако при переходе на вкладку 2 конструктор вызывается снова, но он также выводит Service1. Поэтому refre sh также делается для данных Service1 и не влияет на Service2.

Это нормальное поведение, потому что маршрут не меняется, и мне нужно что-то добавить для сброса службы? Есть ли простой способ устранить это поведение в целом? (Angular 8)

1 Ответ

0 голосов
/ 19 февраля 2020

Похоже, что в моем поиске и устранении неисправностей не было поставщика RefresherServiceToken. Это должно где-то существовать. В моем случае предоставленное было предоставлено в «пустом» модуле, который был родительским для родительского компонента, и поскольку refresher-component находится за пределами дочерних элементов, его также нельзя переопределить на уровне child-component.

Для этого есть три решения:

Самое простое:

Переместите refresher-component внутрь каждого child-component. В моем реальном коде это было немного сложно, но в приведенном выше примере это тривиально. После этого добавьте необходимого поставщика на уровне дочернего компонента, например:

providers: [
    {provide: RefresherServiceToken, useExisting: Service2}
]

В этом случае, даже если на родительском уровне был поставщик, он переопределяется.

Простой в реализации, трудный для чтения / отслеживания позже

Динамически настраивает провайдера на уровне parent-component. Есть несколько способов сделать это, как описано здесь: Как динамически добавлять провайдеров в Injector?

Потенциально самый сложный для реализации, но самый простой для gr asp

Измените способ построения этих страниц: два дочерних компонента должны находиться на двух совершенно разных страницах / маршрутах, тогда как общие части шаблона (скажем, верхний / нижний колонтитулы) находятся в общих компонентах. Это полностью решает проблему, потому что нет ни одного родителя для обоих дочерних компонентов, и поэтому они не могут иметь одного и того же поставщика. Естественно, отдельные провайдеры должны быть определены для каждого из них, как указано в первом примере.

...