Angular Pipes not working when used inside ContentChildren
Dart Version, have tried on 2.7.2 and 2.8.0-dev-20
environment:
sdk: ">=2.7.0 <3.0.0"
AngularDart Version: 5.3.1
dependencies:
angular: ^5.3.1
I ran into an issue with pipes which appears to be an Angular bug unless i'm using it wrong?
To reproduce the issue, I've defined a simple pipe that simply appends a random number to an input:
@Pipe("RandomPipe10")
class RandomPipe10 extends PipeTransform {
String transform(String input) {
return input + Random().nextInt(10).toString();
}
}
Then i defined a simple component to confirm that the pipe on its own works:
@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 {}
Which correctly outputs
Testing Pipe inside ContentChildren
This works: blah19
Now let's define a directive that we can use to add components with:
@Directive(selector: "[contentDirective]")
class ContentDirective {
final TemplateRef template;
ContentDirective(this.template) {
template.createEmbeddedView();
}
}
and let's define a second component:
@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>[];
}
If i now update the first component to render this component, the pipe still renders correctly:
@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 {}
It correctly renders
Testing Pipe inside ContentChildren
This works: blah13
---------------------------------
BLAH
This works: blah2
BLAH
This works: blah6
---------------------------------
This also outputs the correct output similar to the above obviously with different random numbers:
<bug-pipe-test-child>
<div *contentDirective>
{{ 'BLAH' }}
</div>
<div *contentDirective>
{{ 'BLAH' }}
</div>
</bug-pipe-test-child>
If i now include a pipe inside that template, it throws errors and refuses to render
<bug-pipe-test-child>
<div *contentDirective>
{{ 'BLAH' | RandomPipe10 }}
</div>
<div *contentDirective>
{{ 'BLAH' }}
</div>
</bug-pipe-test-child>
This is the error:
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>
and the full stacktrace:
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
Similarly, this works (and correctly adds a blah attribute with value blah):
<bug-pipe-test-child>
<div *contentDirective [attr.blah]="'blah'">
{{ 'BLAH' }}
</div>
<div *contentDirective>
{{ 'BLAH' }}
</div>
</bug-pipe-test-child>
but this throws the same error:
<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:
The generated bug-pipe-test.template.dart looks like this
@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);
}
The error appears to be on .transform
Reposted on StackOverflow: https://stackoverflow.com/questions/61189733/angular-pipes-not-working-when-used-inside-contentchildren
I can reproduce this issue even with built-in pipes, this works and correctly uppercases the output:
This works: {{ 'blah1' | RandomPipe10 | uppercase }}
This throws the same error
<bug-pipe-test-child>
<div *contentDirective [attr.blah]="'blah' | uppercase">
{{ 'BLAH' }}
</div>
<div *contentDirective>
{{ 'BLAH' }}
</div>
</bug-pipe-test-child>
and so does this:
This throws the same error
<bug-pipe-test-child>
<div *contentDirective [attr.blah]="'blah'">
{{ 'BLAH' | uppercase }}
</div>
<div *contentDirective>
{{ 'BLAH' }}
</div>
</bug-pipe-test-child>