Не удается найти родительский сервис во вложенной структурной директиве - PullRequest
2 голосов
/ 13 июня 2019

Я использую Angular 8 для создания своего маленького приложения.В моем приложении у меня есть 2 структурные директивы:

  • parent.directive.ts:
@Directive({
  selector: '[parent]',
  providers: [
    DemoService
  ]
})
export class ParentDirective implements OnInit {

   public constructor(protected viewContainerRef: ViewContainerRef,
                     protected templateRef: TemplateRef<any>, 
                     public demoService: DemoService) {
  }

  public ngOnInit() {
    this.demoService
    .name = 'parent';

    this.viewContainerRef.createEmbeddedView(this.templateRef);
  }
}
  • child.directive.ts:
@Directive({
  selector: '[child]',
  providers: [
    DemoService
  ]
})
export class ChildDirective implements OnInit {

   public constructor(protected viewContainerRef: ViewContainerRef,
                     protected templateRef: TemplateRef<any>, 
                     public demoService: DemoService, 
                     @SkipSelf() public parentDemoService: DemoService) {
  }

  public ngOnInit() {
    this.demoService
    .name = 'parent';

    console.log(this.parentDemoService.name);
  }
}

Все мои 2 директивы инициализируют DemoService, однако в child.directive.ts я также хочу получить доступ к DemoService, который находится в parent.directive.ts.

Следовательно, в child.directive.ts, я объявляю DI следующим образом:

 public constructor(protected viewContainerRef: ViewContainerRef,
                     protected templateRef: TemplateRef<any>, 
                     public demoService: DemoService, 
                     @SkipSelf() public parentDemoService: DemoService) {
  }

Это то, что я использовал на html-странице:

<div *parent>
   <div>Inside parent</div>
      <div *child>
        <div>Inside child</div>
      </div>

    <div *parent>
   <div>Inside parent parent</div>
      <div *child>
        <div>Inside child</div>
      </div>
   </div> 
</div>

   </div> 
</div> 

Я ожидаю, что я могу получить доступ к DemoService вродительская директива через parentDemoService экземпляр, но я получил следующую ошибку:

Ошибка ОШИБКИ: StaticInjectorError (AppModule) [ParentDirective -> DemoService]: StaticInjectorError (Platform: core) [ParentDirective -> DemoService]: NullInjectorError: Нет поставщика услуг DemoService!

Я уже поместил демонстрационный код на stackblitz .

Может кто-нибудь помочь мне в этом?Спасибо.

P / s: Я хочу предоставить новый экземпляр для каждой директивы.Вот почему я использовал провайдера в директиве parent и child

Поскольку некоторые люди не понимают мой вопрос (возможно, он недостаточно ясен), я обновил 2 изображения, чтобы описать мою проблему.

Допустим, DemoService имеет переменную-счетчик, начиная с 1 в родительском и может быть увеличена дочерними структурными директивами.

Это мой ожидаемый результат:

Expected result

Ответы [ 3 ]

0 голосов
/ 13 июня 2019

Для этого вам необходимо реструктурировать все приложение.

Создайте ParentModule с двумя службами ShareService и DemoService в качестве поставщиков и объявите, экспортируйте ParentDirective в этот модуль и импортируйте его в RootModule.

И предоставить DemoService в ChildDirective.

Теперь создайте экземпляр DemoService в ShareService и сделайте этот экземпляр равным ParentDirective, Таким образом, вы можете получить доступ к этому ParentDirective экземпляру в ChildDirective через ShareService.

Проверьте это: stackblitz

0 голосов
/ 14 июня 2019

Это сложный вопрос, поэтому я начну с того, что говорю, что я довольно новичок в angular и мне еще предстоит пройти долгий путь.Но я люблю учиться, поэтому я попытался понять вашу проблему и найти решение для вас, используя Официальную документацию и пример.Поэтому используйте следующую реализацию по своему усмотрению!

В зависимости от того, что именно вы хотите сделать, приложению требуются некоторые изменения в структуре.Насколько я знаю, предоставление сервиса на уровне компонента ограничивает обслуживание этим компонентом и не позволит вам достичь своей цели.Здесь у меня есть два решения для вас:

1 - Определите DemoService и ChildDemoService, который расширяет DemoService в 'root' и вводит ваш DemoService в родительские и дочерние директивы и вводитChildDemoService только в директиве вашего ребенка.Таким образом, у вас будет два экземпляра DemoService в обоих компонентах, но эти экземпляры будут находиться в одном и том же состоянии и могут редактироваться с помощью директив parent и child.У вас также будет childDemoService, который доступен только ребенку (не уверен, нужен ли он вам).

Я обновил ваш код в Stackblitz , чтобы отразить это.Я включил значимые console.log() s для вас, поэтому не забудьте открыть инспектор браузера!

Для получения дополнительной информации обратитесь к Angular Official Documentation и поиграйтесь с Их примером.

2- Создайте отдельные модули, которые объявляют ваши дочерние и родительские директивы и предоставляют вашу службу в этом модуле, чтобы экземпляры вашей службы были доступны только через эти две директивы, а сами директивы могут бытьдоступны везде, где вы хотите, чтобы они были доступны в приложении (в зависимости от вашей реализации)

Пожалуйста, дайте мне знать, если у вас есть какие-либо вопросы или опасения, так как это был интригующий вопрос для меня.

Ура, Алекс

0 голосов
/ 13 июня 2019

Пояснение:

Сообщения об ошибках сообщают, что angular не может внедрить службу, необходимую для родительской директивы. Вы должны помочь angular определить услугу, указав данные поставщика. Есть несколько способов указать.

Решение: Введите providers: [DemoService] в app.module.ts, чтобы решить.

...