Angular 8-如何识别(并订阅)传递给组件的模板中的元素

问题描述 投票:1回答:1

[我有一个父组件,它使用模板定义项目的标记(我将场景剥离为裸露的骨头),呈现了一个“ 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次尝试彼此独立。

1。使用模板引用变量

[想法:正如#itemTemplate引用用于标识模板一样,请使用相同的语法创建对所需组件(要订阅)的引用。然后通过新的@Input将引用传递给“ 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>

结果/问题:

在“项目”组件中,subscribeToThis是未定义的。 (由于#subscribeToThis参考的范围,我认为它是未定义的-是吗?)因此,“ item”组件无法使用它来查找要订阅的元素。

类似于此,具有相同的结果-我试图在“ 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。

2。使用css类标记和查找元素

[想法:为所需的#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”组件中的单击处理程序。

此方法的问题:

出于充分原因,不建议使用此低级别方法。

3。在模板的元素中直接分配点击处理程序

想法:

// 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 dom-events angular2-template
1个回答
0
投票

在Angular中,通知父母已发生事件的方法是在子组件内部使用@Ouput装饰器。

例如子组件

© www.soinside.com 2019 - 2024. All rights reserved.