Angular Трубы не работают при использовании внутри ContentChildren - PullRequest
2 голосов
/ 13 апреля 2020

Я столкнулся с проблемой, которая выглядит как ошибка Angular, если я не использую ее неправильно?

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

@Pipe("RandomPipe10")
class RandomPipe10 extends PipeTransform {
  String transform(String input) {
    return input + Random().nextInt(10).toString();
  }
}

Затем я определил простой компонент для подтверждения того, что канал сам по себе работает:

@Component(
  selector: "bug-pipe-test",
  // language=HTML
  template: """
      Testing Pipe inside ContentChildren
      <br />
      This works: {{ 'blah1' | RandomPipe10 }}
    """,
  directives: const [
    BugPipeTestChild,
    NgFor,
    NgTemplateOutlet,
  ],
  pipes: const [
    RandomPipe10,
  ],
)
class BugPipeTest {}

, который правильно выводит

Testing Pipe inside ContentChildren
This works: blah19

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

@Directive(selector: "[contentDirective]")
class ContentDirective {
  final TemplateRef template;

  ContentDirective(this.template) {
    template.createEmbeddedView();
  }
}

и давайте определим второй компонент:

@Component(
  selector: "bug-pipe-test-child",
  // language=HTML
  template: """
    <hr>
    <template ngFor let-item [ngForOf]="contentItems ?? []">
        <div class="flex-grow:0 dark">
            <template [ngTemplateOutlet]="item.template">
            </template>
            This works: {{ 'blah' | RandomPipe10 }}
        </div>
    </template>
    <hr>
  """,
  directives: const [
    NgFor,
    NgTemplateOutlet,
    ContentDirective,
  ],
  pipes: const [
    RandomPipe10,
  ],
)
class BugPipeTestChild {
  @Input()
  @ContentChildren(ContentDirective)
  List<ContentDirective> contentItems = <ContentDirective>[];
}

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

@Component(
  selector: "bug-pipe-test",
  // language=HTML
  template: """
      Testing Pipe inside ContentChildren
      <br />
      This works: {{ 'blah1' | RandomPipe10 }}
      <bug-pipe-test-child>
          <div *contentDirective>
             BLAH
          </div>
          <div *contentDirective>
            BLAH
          </div>
      </bug-pipe-test-child>
    """,
  directives: const [
    BugPipeTestChild,
    NgFor,
    NgTemplateOutlet,
    ContentDirective,
  ],
  pipes: const [
    RandomPipe10,
  ],
)
class BugPipeTest {}

правильно отображает

Testing Pipe inside ContentChildren
This works: blah13
---------------------------------
BLAH
This works: blah2
BLAH
This works: blah6
---------------------------------

Это также выводит правильный вывод, аналогичный приведенному выше, очевидно, с различными случайными числами:

      <bug-pipe-test-child>
          <div *contentDirective>
             {{ 'BLAH' }}
          </div>
          <div *contentDirective>
             {{ 'BLAH' }}
          </div>
      </bug-pipe-test-child>

Если я теперь добавлю канал в этот шаблон, он выдаст ошибки и откажется отрисовать

      <bug-pipe-test-child>
          <div *contentDirective>
             {{ 'BLAH' | RandomPipe10 }}
          </div>
          <div *contentDirective>
             {{ 'BLAH' }}
          </div>
      </bug-pipe-test-child>

Это ошибка:

dart_sdk.js:97372 EXCEPTION: TypeError: Cannot read property 'bind' of undefined
STACKTRACE: 
dart:sdk_internal 3900:20                                        bind
package:lulacomponents/test/bug-pipe-test.template.dart 114:120  build
package:angular/src/core/linker/app_view.dart 244:12             create
package:angular/src/core/linker/template_ref.dart 28:9           createEmbeddedView
package:lulacomponents/test/bug-pipe-test.dart 82:14             new
package:lulacomponents/test/bug-pipe-test.template.dart 65:37    build
package:angular/src/core/linker/app_view.dart 244:12             create
package:lulacomponents/test/bug-pipe-test.template.dart 156:17   build
package:angular/src/core/linker/app_view.dart 258:12             createHostView
package:angular/src/core/linker/component_factory.dart 104:20    create
package:angular/src/core/application_ref.dart 70:41              <fn>
package:angular/src/core/change_detection/host.dart 247:26       <fn>
package:angular/src/core/zone/ng_zone.dart 132:18                <fn>
dart:sdk_internal 30626:14                                       run
package:angular/src/core/zone/ng_zone.dart 129:18                [_run]
dart:sdk_internal 30943:14                                       run
package:angular/src/core/zone/ng_zone.dart 291:23                run
package:angular/src/core/application_ref.dart 139:52             runInZone
package:angular/src/core/change_detection/host.dart 245:5        run
package:angular/src/core/application_ref.dart 69:23              bootstrap
package:angular/src/bootstrap/run.dart 207:16                    runApp
bug_pipe.dart 5:2                                                main
%3Canonymous%3E 1:8                                              <fn>
dwds/src/injected/client.js 8188:15                              runMain
dwds/src/injected/client.js 22128:19                             <fn>
dwds/src/injected/client.js 3550:15                              $protected
dwds/src/injected/client.js 10697:12                             call$2
dwds/src/injected/client.js 3514:20                              _asyncStartSync
dwds/src/injected/client.js 22140:16                             $call$body$main__closure
dwds/src/injected/client.js 22072:19                             call$1
dwds/src/injected/client.js 3852:16                              _rootRunUnary
dwds/src/injected/client.js 12004:128                            runUnary$2$2
dwds/src/injected/client.js 11932:14                             runUnaryGuarded$1$2
dwds/src/injected/client.js 11491:19                             _sendData$1
dwds/src/injected/client.js 11645:62                             perform$1
dwds/src/injected/client.js 11694:14                             call$0
dwds/src/injected/client.js 3715:21                              _microtaskLoop
dwds/src/injected/client.js 3721:11                              _startMicrotaskLoop
dwds/src/injected/client.js 10572:9                              call$1
dwds/src/injected/client.js 1169:26                              invokeClosure
dwds/src/injected/client.js 1188:18                              <fn>

и полная трассировка стека:

dart_sdk.js:97372 EXCEPTION: TypeError: Cannot read property 'bind' of undefined
STACKTRACE: 
dart:sdk_internal 3900:20                                        bind
package:lulacomponents/test/bug-pipe-test.template.dart 114:120  build
package:angular/src/core/linker/app_view.dart 244:12             create
package:angular/src/core/linker/template_ref.dart 28:9           createEmbeddedView
package:lulacomponents/test/bug-pipe-test.dart 82:14             new
package:lulacomponents/test/bug-pipe-test.template.dart 65:37    build
package:angular/src/core/linker/app_view.dart 244:12             create
package:lulacomponents/test/bug-pipe-test.template.dart 156:17   build
package:angular/src/core/linker/app_view.dart 258:12             createHostView
package:angular/src/core/linker/component_factory.dart 104:20    create
package:angular/src/core/application_ref.dart 70:41              <fn>
package:angular/src/core/change_detection/host.dart 247:26       <fn>
package:angular/src/core/zone/ng_zone.dart 132:18                <fn>
dart:sdk_internal 30626:14                                       run
package:angular/src/core/zone/ng_zone.dart 129:18                [_run]
dart:sdk_internal 30943:14                                       run
package:angular/src/core/zone/ng_zone.dart 291:23                run
package:angular/src/core/application_ref.dart 139:52             runInZone
package:angular/src/core/change_detection/host.dart 245:5        run
package:angular/src/core/application_ref.dart 69:23              bootstrap
package:angular/src/bootstrap/run.dart 207:16                    runApp
bug_pipe.dart 5:2                                                main

Точно так же работает (и правильно добавить sa blah атрибут со значением blah):

      <bug-pipe-test-child>
          <div *contentDirective [attr.blah]="'blah'">
             {{ 'BLAH' }}
          </div>
          <div *contentDirective>
             {{ 'BLAH' }}
          </div>
      </bug-pipe-test-child>

, но выдает ту же ошибку:

      <bug-pipe-test-child>
          <div *contentDirective [attr.blah]="'blah' | RandomPipe10">
             {{ 'BLAH' }}
          </div>
          <div *contentDirective>
             {{ 'BLAH' }}
          </div>
      </bug-pipe-test-child>
dart_sdk.js:97372 EXCEPTION: TypeError: Cannot read property 'bind' of undefined
STACKTRACE: 

Сгенерированный bug-pipe-test.template.dart выглядит следующим образом

  @override
  ComponentRef<import1.BugPipeTest> build() {
    final doc = import8.document;
    _el_0 = doc.createElement('div');
    final _text_1 = import11.appendText(_el_0, 'BLAH');
    _pipe_RandomPipe10_0_1 = import13.pureProxy1(import9.unsafeCast<ViewBugPipeTest0>(parentView)._pipe_RandomPipe10_0.transform);
    init1(_el_0);
  }

Кажется, он не работает на .transform, не уверен, откуда происходит привязка. Это ошибка?

Зарегистрировался один раз: https://github.com/dart-lang/angular/issues/1888

и если да, то есть ли какое-то решение для этого в то же время?

РЕДАКТИРОВАТЬ

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

      This works: {{ 'blah1' | RandomPipe10 | uppercase }}

Это выдает ту же ошибку

      <bug-pipe-test-child>
          <div *contentDirective [attr.blah]="'blah' | uppercase">
             {{ 'BLAH' }}
          </div>
          <div *contentDirective>
             {{ 'BLAH' }}
          </div>
      </bug-pipe-test-child>
...