Angular 9 расширяет ServiceProviderComponent с помощью провайдеров

У меня есть компонент ServiceProviderComponent, единственной задачей которого является предоставление услуги. Я хочу расширить этот ServiceProviderComponent другим компонентом (HelloComponent), чтобы я мог использовать службу в нем и его дочерних элементах. Как это возможно сделать без вызова super(); в конструкторе HelloComponent с этой службой в качестве аргумента? Я попытался внедрить инжектор и предоставить услугу с помощью Injector.create(), но это не сработало.

Я создал демо-версию Stackblitz. В hello.component я хочу использовать предоставленный ServiceProviderComponent экземпляр токена инъекции BASE_TEST_TOKEN, но всегда используется глобальный экземпляр.

Возможно ли вообще иметь что-то вроде компонента ServiceProvider, который я могу расширить?

ОБНОВЛЕНИЕ 1 Я обновил свой пример директивой. Я хочу, чтобы эта директива также использовала экземпляр службы hello.component. Как я могу это сделать?


person Daniel    schedule 14.05.2020    source источник
comment
Я знаю, что это не отвечает на ваш вопрос, но почему вы хотите создать компонент поставщика услуг, а не просто напрямую внедрять необходимые услуги?   -  person marcel    schedule 14.05.2020
comment
@marcel я хочу иметь несколько экземпляров службы в разных компонентах, но я не хочу иметь строки «предоставить» в каждом из этих компонентов.   -  person Daniel    schedule 14.05.2020


Ответы (1)


Хотя немного сложно понять, чего вы хотите, но я считаю, что это возможно, используя Injector и создавая новый в конструкторе с помощью метода Injector.create.

Хотя метод .create разрешает только так называемый StaticProviders, вы можете внедрить другие сервисы, используя свойство deps с `useFactory:

рабочий пример

@Component({
  selector: 'hello',
  template: `<h1>Hello {{name}}!</h1>`,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent extends ServiceProviderComponent implements OnInit {
  @Input() name: string;

  ngOnInit() {
    this.name = this.testService.test();
  }
}

В stackblitz показана другая конфигурация @Directive, но это потому, что стек основан на angular 8. С angular 9 вы можете (и должны) использовать пустую директиву. В любом случае, когда вы расширяете компонент/директиву, все, что у вас есть внутри базового декоратора, не будет прочитано/расширено

@Directive()
export class ServiceProviderComponent {
  protected testService: BaseTestService;

  constructor(injector: Injector) {
    injector = Injector.create(
      [{ provide: BASE_TEST_TOKEN, useFactory: (...deps) => new TestServiceService(), deps: [] }],
      injector
    );

    this.testService = injector.get(BASE_TEST_TOKEN);
  }
}

--

Для вашего обновления вам, к сожалению, необходимо расширить сервисный компонент из вашей директивы, ввести инжектор и передать его в супервызове:

рабочий пример

Кроме того, создается впечатление, что вы работаете в противоречии с предикатами angular. Вы пытаетесь решить что-то, что следует либо решить по-другому, либо вообще не решать. Из вашего вопроса я не могу понять, какова ваша конечная цель со всем этим

person Poul Kruijt    schedule 14.05.2020
comment
Спасибо за ваш ответ. Ваш пример почти то, что мне нужно. У меня есть еще одна проблема, я обновил свой пост обновленной версией вашего примера. Не могли бы вы рассказать мне, как это сделать? - person Daniel; 14.05.2020
comment
Спасибо за обновление. Моя конечная цель заключается в том, что у меня есть несколько компонентов с асинхронной инициализацией, всем им нужен собственный http-запрос для получения данных. Но они могут иметь зависимости друг от друга, поэтому я пытаюсь создать службу, в которой я могу контролировать свои собственные жизненные циклы инициализации DataSource всех компонентов. Эти компоненты создаются динамически директивой, и совокупность этих компонентов может появляться несколько раз. Итак, я хочу, чтобы для каждого экземпляра этого созвездия был собственный экземпляр моего сервиса. - person Daniel; 15.05.2020