Это сводит меня с ума:
- убедитесь, что вы проверяете консоль в стеке
Вот STACKBLITZ , который описывает мою проблему бест.
В двух словах. Я хочу, чтобы "Материал" внутри ЗАКРЫТО Панели расширения НЕ проверялся ChangeDetection (исключить из ChangeDetection).
cd-check-comp: Projected from Parent to Child
равен STAMPED OUT из Parent
-Просмотр, поэтому он проверяется при проверке parent
. Это ожидаемое поведение, но НЕ ЖЕЛАЕТ .
Вопрос:
Как поставить проекцию ng-template
(в этом примере cdkPortal / TemplatePortal) в те же ViewContainer
, что и cd-check-comp: Im in Childs View
?
Как изменить / переключить ViewContainerRef
на ng-template
. Я хотел бы «выполнить / кодировать» переключатель внутри Child
-компонента.
Stackblitz Сохранить:
@Component({
selector: "parent",
template: `
<button (click)="tick()">Trigger app.tick()</button>
<mat-expansion-panel #ep1>
<mat-expansion-panel-header>
<mat-panel-title>
Stuff inside should only be checked if open
</mat-panel-title>
</mat-expansion-panel-header>
<child [disableCD]="!ep1.expanded">
<ng-template cdkPortal>
<cd-check-comp name='Projected from Parent to Child'></cd-check-comp>
</ng-template>
</child>
</mat-expansion-panel>
<cd-check-comp name='Im in parents View.'></cd-check-comp>
<p> Main Goal: <b>cd-check-comp: Projected from Parent to Child</b> should not be "checked" when the Panel is closed for the first time.</p>
`,
})
export class Parent {
tick() { setTimeout(() => {}); }
}
@Component({
selector: 'child',
template: `
<ng-template [cdkPortalOutlet]="_portal"></ng-template>
<cd-check-comp name="Im in Childs View"></cd-check-comp>
`,
})
export class Child implements OnInit {
@ContentChild(CdkPortal, {static: true}) _lazyPortal: CdkPortal;
@Input() disableCD: boolean;
_opened: BehaviorSubject<boolean>;
_portal: TemplatePortal;
constructor(
private _changeDetectorRef: ChangeDetectorRef, private _vcr: ViewContainerRef
) {
}
ngOnInit() {
this._opened = new BehaviorSubject(this.disableCD);
}
ngDoCheck() {
console.log('Child checked')
}
ngOnChanges(sc: SimpleChanges) {
// return;
this.disableCD ? this._changeDetectorRef.detach() : this._changeDetectorRef.reattach();
if (this._opened) { this._opened.next(this.disableCD); }
}
ngAfterContentInit() {
if (this._lazyPortal) {
this._opened.pipe(
startWith(null!),
filter(() => this._opened.value && !this._portal),
take(1)
).subscribe(() => {
this._portal = this._lazyPortal;
});
}
}
}
@Component({
selector: "cd-check-comp",
template: "<p>cd-check-comp: <b>{{name ? name : instanceCounter}}</b></p>",
styles: [':host { display: block; border: 1px dashed black}']
})
export class CdCheckComp implements DoCheck {
static counter = 0;
@Input() name: string;
instanceCounter: number;
constructor(private _vcr: ViewContainerRef) {
this.instanceCounter = ++CdCheckComp.counter;
}
ngDoCheck() {
console.log("checked:" + (this.name ? this.name : this.instanceCounter));
}
}