Skip to content

No provider found for structured directive  #64

@genesistms

Description

@genesistms

Which ng* package(s) are the source of the bug?

ngcompiler

Which operating system(s) does this bug appear on?

Linux

Which browser(s) does this bug appear on?

Chrome 115.0.5790.98 (Official Build) (64-bit)

Is this a regression?

Yes

Description

The Child should be provided.

Nesting of html elements should not affect this.

Please provide the steps to reproduce the bug

import 'package:ngdart/angular.dart';

import 'main.template.dart' as self;

void main() {
  runApp(self.AppComponentNgFactory);
}

abstract class Child {}

@Directive(
  selector: '[strDir]',
  providers: [ExistingProvider(Child, ChildDirective)],
)
class ChildDirective implements Child, OnInit {
  final TemplateRef _templateRef;
  final ViewContainerRef _viewContainerRef;
  ChildDirective(this._templateRef, this._viewContainerRef);

  @override
  void ngOnInit() {
    _viewContainerRef.createEmbeddedView(_templateRef);
  }
}

@Component(
  selector: 'child',
  template: '',
  changeDetection: ChangeDetectionStrategy.OnPush,
)
class ChildComponent {
  final Child abstract;
  ChildComponent(this.abstract);
}

@Component(
  selector: 'my-app',
  template: r'''
<!-- THIS ONE WORKS -->
<template strDir>
    <child></child>
</template>

<!-- THIS ONE DOES NOT -->
<div>
    <template strDir>
        <child></child>
    </template>
</div>
  ''',
  directives: [ChildComponent, ChildDirective],
  changeDetection: ChangeDetectionStrategy.OnPush,
)
class AppComponent {}

Please provide the exception or error you saw

EXCEPTION: No provider found for Child:
  ChildComponent ->
  Child.

Please provide the dependency environment you discovered this bug in (run dart pub deps -s compact)

Dart SDK 2.18.7
testing 0.0.1

dependencies:
- ngdart 7.1.1 [built_collection built_value collection intl js logging meta stack_trace stream_transform ngast ngcompiler build build_config code_builder csslib path quiver source_gen source_span]

dev dependencies:
- build_runner 2.3.3 [args async analyzer build build_config build_daemon build_resolvers build_runner_core code_builder collection crypto dart_style frontend_server_client glob graphs http_multi_server io js logging meta mime package_config path pool pub_semver pubspec_parse shelf shelf_web_socket stack_trace stream_transform timing watcher web_socket_channel yaml]
- build_web_compilers 3.2.6 [analyzer archive bazel_worker build build_config build_modules collection glob js logging path pool scratch_space source_maps source_span stack_trace]

transitive dependencies:
- _fe_analyzer_shared 47.0.0 [meta]
- analyzer 4.7.0 [_fe_analyzer_shared collection convert crypto glob meta package_config path pub_semver source_span watcher yaml]
- archive 3.3.7 [crypto path pointycastle]
- args 2.4.1
- async 2.11.0 [collection meta]
- bazel_worker 1.0.2 [async protobuf]
- boolean_selector 2.1.1 [source_span string_scanner]
- build 2.3.1 [analyzer async convert crypto glob logging meta path]
- build_config 1.1.1 [checked_yaml json_annotation path pubspec_parse yaml]
- build_daemon 3.1.1 [built_collection built_value http_multi_server logging path pool shelf shelf_web_socket stream_transform watcher web_socket_channel]
- build_modules 4.0.6 [analyzer async bazel_worker build build_config collection crypto glob graphs json_annotation logging path scratch_space stream_transform]
- build_resolvers 2.0.10 [analyzer async build crypto graphs logging path package_config pool pub_semver stream_transform yaml]
- build_runner_core 7.2.7 [async build build_config build_resolvers collection convert crypto glob graphs json_annotation logging meta path package_config pool timing watcher yaml]
- build_test 2.1.7 [async build build_config build_resolvers crypto glob html logging matcher package_config path stream_transform test test_core watcher]
- built_collection 5.1.1
- built_value 8.6.1 [built_collection collection fixnum meta]
- charcode 1.3.1
- checked_yaml 2.0.2 [json_annotation source_span yaml]
- clock 1.1.1
- code_builder 4.4.0 [built_collection built_value collection matcher meta]
- collection 1.17.2
- convert 3.1.1 [typed_data]
- coverage 1.6.3 [args logging package_config path source_maps stack_trace vm_service]
- crypto 3.0.2 [typed_data]
- csslib 0.17.2 [source_span]
- dart_style 2.2.4 [analyzer args path pub_semver source_span]
- file 6.1.4 [meta path]
- fixnum 1.0.1
- frontend_server_client 3.2.0 [async path]
- glob 2.1.1 [async collection file path string_scanner]
- graphs 2.3.1 [collection]
- html 0.15.3 [csslib source_span]
- http_multi_server 3.2.1 [async]
- http_parser 4.0.2 [collection source_span string_scanner typed_data]
- intl 0.17.0 [clock path]
- io 1.0.4 [meta path string_scanner]
- js 0.6.5 [meta]
- json_annotation 4.8.0 [meta]
- logging 1.1.1
- matcher 0.12.16 [async meta stack_trace term_glyph test_api]
- meta 1.9.1
- mime 1.0.4
- ngast 2.1.4 [charcode collection meta source_span string_scanner]
- ngcompiler 2.1.3 [ngdart ngast analyzer args build build_test code_builder collection csslib dart_style logging meta package_config path source_gen source_span stack_trace]
- node_preamble 2.0.2
- package_config 2.1.0 [path]
- path 1.8.3
- pointycastle 3.7.3 [collection convert js]
- pool 1.5.1 [async stack_trace]
- protobuf 2.1.0 [fixnum collection meta]
- pub_semver 2.1.4 [collection meta]
- pubspec_parse 1.2.3 [checked_yaml collection json_annotation pub_semver yaml]
- quiver 3.2.1 [matcher]
- scratch_space 1.0.1 [build crypto path pool]
- shelf 1.4.1 [async collection http_parser path stack_trace stream_channel]
- shelf_packages_handler 3.0.2 [path shelf shelf_static]
- shelf_static 1.1.2 [convert http_parser mime path shelf]
- shelf_web_socket 1.0.4 [shelf stream_channel web_socket_channel]
- source_gen 1.2.6 [analyzer async build dart_style glob meta path source_span yaml]
- source_map_stack_trace 2.1.1 [path source_maps stack_trace]
- source_maps 0.10.12 [source_span]
- source_span 1.10.0 [collection path term_glyph]
- stack_trace 1.11.1 [path]
- stream_channel 2.1.1 [async]
- stream_transform 2.1.0
- string_scanner 1.2.0 [source_span]
- term_glyph 1.2.1
- test 1.24.3 [analyzer async boolean_selector collection coverage http_multi_server io js node_preamble package_config path pool shelf shelf_packages_handler shelf_static shelf_web_socket source_span stack_trace stream_channel typed_data web_socket_channel webkit_inspection_protocol yaml test_api test_core matcher]
- test_api 0.6.0 [async boolean_selector collection meta source_span stack_trace stream_channel string_scanner term_glyph]
- test_core 0.5.3 [analyzer async args boolean_selector collection coverage frontend_server_client glob io meta package_config path pool source_map_stack_trace source_maps source_span stack_trace stream_channel vm_service yaml test_api]
- timing 1.0.1 [json_annotation]
- typed_data 1.3.2 [collection]
- vm_service 11.2.0
- watcher 1.0.2 [async path]
- web_socket_channel 2.4.0 [async crypto stream_channel]
- webkit_inspection_protocol 1.2.0 [logging]
- yaml 3.1.1 [collection source_span string_scanner]

Anything else?

Interesting part from generated template:

App component view
working:

  @override
  void build() {
    final parentRenderNode = this.initViewRoot();
    final _anchor_0 = import11.appendAnchor(parentRenderNode);

    // THIS IS INTERESTING
    // parent is null
    this._appEl_0 = ViewContainer(0, null, this, _anchor_0);

    var _TemplateRef_0_8 = TemplateRef(this._appEl_0, viewFactory_AppComponent1);
    this._ChildDirective_0_9 = import1.ChildDirective(_TemplateRef_0_8, this._appEl_0);
    if (import13.isDevToolsEnabled) {
      import13.Inspector.instance.registerDirective(_anchor_0, this._ChildDirective_0_9);
    }
    final _text_1 = import11.appendText(parentRenderNode, '\n');
    final _text_2 = import11.appendText(parentRenderNode, '\n');
    final _text_3 = import11.appendText(parentRenderNode, '\n');
    final _text_4 = import11.appendText(parentRenderNode, '\n');
    final _text_5 = import11.appendText(parentRenderNode, '\n');
  }

  @override
  dynamic injectorGetInternal(dynamic token, int nodeIndex, dynamic notFoundResult) {
    if ((identical(token, import1.Child) && (0 == nodeIndex))) {
      return this._ChildDirective_0_9;
    }
    return notFoundResult;
  }

NOT working

  @override
  void build() {
    final parentRenderNode = this.initViewRoot();
    final _text_0 = import11.appendText(parentRenderNode, '\n');
    final _text_1 = import11.appendText(parentRenderNode, '\n');
    final _text_2 = import11.appendText(parentRenderNode, '\n');
    final _text_3 = import11.appendText(parentRenderNode, ' ');
    final doc = import6.document;
    final _el_4 = import11.appendDiv(doc, parentRenderNode);
    final _anchor_5 = import11.appendAnchor(_el_4);

    // THIS IS INTERESTING
    // parent index is 4
    this._appEl_5 = ViewContainer(5, 4, this, _anchor_5);

    var _TemplateRef_5_8 = TemplateRef(this._appEl_5, viewFactory_AppComponent1);
    this._ChildDirective_5_9 = import1.ChildDirective(_TemplateRef_5_8, this._appEl_5);
    if (import13.isDevToolsEnabled) {
      import13.Inspector.instance.registerDirective(_anchor_5, this._ChildDirective_5_9);
    }
  }

  @override
  dynamic injectorGetInternal(dynamic token, int nodeIndex, dynamic notFoundResult) {
    if ((identical(token, import1.Child) && (5 == nodeIndex))) {
      return this._ChildDirective_5_9;
    }
    return notFoundResult;
  }

And View for structured directive

Working:

  void build() {
    this._compView_0 = ViewChildComponent0(this, 0);
    final _el_0 = this._compView_0.rootElement;
    this._ChildComponent_0_5 = (import5.isDevMode
        ? import9.debugInjectorWrap(import1.ChildComponent, () {

            // CORECT
            return import1.ChildComponent((this.parentView!).injectorGet(import1.Child, this.parentIndex));

          })
        : import1.ChildComponent((this.parentView!).injectorGet(import1.Child, this.parentIndex)));
    this._compView_0.create(this._ChildComponent_0_5);
    this.initRootNode(_el_0);
  }

NOT working

  void build() {
    this._compView_0 = ViewChildComponent0(this, 0);
    final _el_0 = this._compView_0.rootElement;
    this._ChildComponent_0_5 = (import5.isDevMode
        ? import9.debugInjectorWrap(import1.ChildComponent, () {

            // WRONG
            // parentView.parentView 
            return import1.ChildComponent(((this.parentView!).parentView!).injectorGet(import1.Child, (this.parentView!).parentIndex));

          })
        : import1.ChildComponent(((this.parentView!).parentView!).injectorGet(import1.Child, (this.parentView!).parentIndex)));
    this._compView_0.create(this._ChildComponent_0_5);
    this.initRootNode(_el_0);
  }

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions