[我有一个父组件,它使用模板定义项目的标记(我将场景剥离为裸露的骨头),呈现了一个“ item”组件:
// parent component template
<item [model]="itemModel" [template]="itemTemplate"></item>
<ng-template #itemTemplate let-model="model">
<div>AAA {{model.property1}}</div>
<div>BBB {{model.property2}}</div>
<div>CCC {{model.property3}}</div>
</ng-template>
// "item" component template
<ng-container [ngTemplateOutlet]="template" [ngTemplateOutletContext]="{model: model}"></ng-container>
在“ item”组件代码中,我需要订阅#itemTemplate中的元素之一(例如“ AAA” div)的click事件。问题在于,它是父组件,它定义了要订阅#itemTemplate中的哪些元素。开发人员可以在父组件中对此进行硬编码(如何精确地做到这一点是这里问题的一部分)。同时,点击处理程序需要位于“ item”组件内(以封装点击处理功能-父组件无需对此进行关注。)>
我尝试了三种方法来做到这一点,但我都不喜欢,我想知道是否有更好的方法。这3次尝试彼此独立。
[想法:正如#itemTemplate引用用于标识模板一样,请使用相同的语法创建对所需组件(要订阅)的引用。然后通过新的@Input将引用传递给“ item”组件。
在“项目”组件中,subscribeToThis是未定义的。 (由于#subscribeToThis参考的范围,我认为它是未定义的-是吗?)因此,“ item”组件无法使用它来查找要订阅的元素。// parent component template // the "item" component now takes an additional input "subscribeToThis" <item [model]="itemModel" [template]="itemTemplate" [subscribeToThis]="subscribeToThis"></epbt-card-list> <ng-template #itemTemplate let-model="model"> // the #subscribeToThis reference on the div below is used above as the value // for the subscribeToThis input of the child component; // but it's always undefined ... <div #subscribeToThis >AAA {{model.property1}}</div> <div>BBB {{model.property2}}</div> <div>CCC {{model.property3}}</div> </ng-template>
结果/问题:
类似于此,具有相同的结果-我试图在“ item”组件类中找到#subscribeToThis引用,如下所示:
// bits from child component class @ViewChild('subscribeToThis', {static: false}) elementToSubscribeTo: TemplateRef<any>; ngAfterViewInit() { // this.elementToSubscribeTo is undefined here; // if "things worked", this.elementToSubscribeTo would refer to the element to whose click event I need to subscibe to }
但是再次未定义elementToSubscribeTo。
[想法:为所需的#itemTemplate元素分配一个特殊的类(在下面的示例中为“ subscribe-to-this”):
// parent component template <ng-template #itemTemplate let-model="model"> // note the class on this div; you can use low-level tools to find the element // by its class, but that's not "clean angular" <div class="subscribe-to-this">AAA {{model.property1}}</div> <div>BBB {{model.property2}}</div> <div>CCC {{model.property3}}</div> </ng-template>
然后,在“项目”组件中,将ElementRef和Renderer2注入其中。使用它们,我可以按类查找元素,然后订阅其click事件。
[结果/成功:
“ item”组件将找到该元素,并且对该元素的click事件的订阅的确触发了“ item”组件中的单击处理程序。此方法的问题:
出于充分原因,不建议使用此低级别方法。想法:
// parent component template <ng-template #itemTemplate let-model="model"> // the click handler is assigned right here in the template; // note that the event handler is a function on the model // that is passed to the child component; that function needs to be // added to the model "artificially" since the model shouldn't need to be aware // of how it's handled in the "item" component; that's one of the bad points // in this attempt <div (click)="model.clickHandler()">AAA {{model.property1}}</div> <div>BBB {{model.property2}}</div> <div>CCC {{model.property3}}</div> </ng-template>
为此,必须将clickHandler()函数添加到模型中(例如,在“ item”组件的onNgInit中)。进行这种体操的原因是#itemTemplate中的使用相对简单。
[结果/成功:
单击正确的元素时将调用clickHandler()。此方法的问题:
父组件必须知道魔术函数名称。这不是一个破坏交易的方法,但是离一个干净的黑匣子组件还有一步之遥。
如果消费者(父母)之后需要使用itemModel数据,则“附加”函数clickHandler()不太适合包含在其中。当父级返回数据并添加一些“垃圾”时,这是不好的。我知道我可以从对象中删除它,但是感觉就像是兔子洞的开始。
我是Angular的新手,我希望我只是缺少一些技术,它可以使我清楚地实现此功能,同时将“ item”组件保持为“ black-boxy”。感谢您的任何想法或见解。
我有一个父组件,它使用模板定义项目的标记(我将场景剥离成裸露的骨头),从而呈现了一个“ item”组件://父组件模板
在Angular中,通知父母已发生事件的方法是在子组件内部使用@Ouput
装饰器。
例如子组件