Angular 2 innerHTML(单击)绑定

Pau*_*erc 24 angular

我有一个如此大的html菜单,我决定绑定,以便能够进行几个子菜单下拉,并避免HTML代码重复.父>孩子(也是父母)>孩子......

对于上下文:在ng2_msList/msList.components.ts中,ColumnsManagements.ts作为this.ColumnsManagementInstance导入.innerHTML菜单正确显示在ng2_msList/pages/list.html中:

<!-- COLUMNS DROPDOWN BUTTON -->
<ul [innerHTML]="msList.ColumnsManagementInstance.columnMenu" class="dropdown-menu" role="menu"> </ul>
Run Code Online (Sandbox Code Playgroud)

使用(在我的代码的一个非常简化的版本中):(感谢这个Stack Q)

setHtmlColumnsMenu() {
     var self = this;
     var htmlcolumnsmenu = '';
     [...]
     htmlcolumnsmenu += this.createColumnsList(this.getNoneRelationalColumns(true));

     // which return something like a lot of html content and sometime in it : 
     // <a href="javascript:;" (click)="msList.ColumnsManagementInstance.toogleColumn(column)">
     [...]
     return htmlcolumnsmenu;
}
Run Code Online (Sandbox Code Playgroud)

但是(单击)="msList.ColumnsManagementInstance.toogleColumn(列)"(以前在html内容中)不再有效.它在视图中写为标签中的简单文本(在未显示的innerHtml之前).

我无法达到让它重新运作的方法.我测试多种方式来调用函数或我在网站链接中发现作为对昂文件部分,这里的例子.这些示例调用一个非常容易在同一文件/上下文中设置的函数(click)="MyAction()"但是在我的上下文中我无法正确调用它.

应用程序架构可能不像Angular2点击调用所期望的那样.

Gün*_*uer 32

这是设计的.Angular不[innerHTML]="..."以任何方式处理由(除了清理)添加的HTML .它只是将它传递给浏览器,就是这样.

如果要动态添加包含绑定的HTML,需要将其包装在Angular2组件中,那么可以使用例如添加它 ViewContainerRef.createComponent()

有关完整示例,请参阅Angular 2动态选项卡,其中包含用户单击所选组件

较少的Angulary方式是注入ElementRef,使用添加的HTML访问

elementRef.nativeElement.querySelector('a').addEventListener(...)
Run Code Online (Sandbox Code Playgroud)

  • 我们需要听到的并不总是我们想要听到的:/谢谢,这肯定是我所需要的,即使这意味着我错了;)接受! (2认同)

Wil*_*ilt 8

我知道这个问题有两种解决方案:

1) 使用Renderer2在渲染时添加点击事件

在此解决方案中,Renderer2用于向元素添加单击事件侦听器并按其类型 HTMLAnchorElement 过滤目标。

public ngOnInit() {
  // Solution for catching click events on anchors using Renderer2:
  this.removeEventListener = this.renderer.listen(this.elementRef.nativeElement, 'click', (event) => {
    if (event.target instanceof HTMLAnchorElement) {
      // Your custom anchor click event handler
      this.handleAnchorClick(event);
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

带有演示的 StackBlitz

2)使用ElementRefquerySelectorAll之后查看init

在这个解决方案中,所有的锚元素都是从ElementRefusing中找到的,querySelectorAll并添加了一个自定义的点击处理程序。这必须在视图初始化之后完成,以便渲染 DOM 并且我们可以查询渲染的元素。

public ngAfterViewInit() {
  // Solution for catching click events on anchors using querySelectorAll:
  this.anchors = this.elementRef.nativeElement.querySelectorAll('a');
  this.anchors.forEach((anchor: HTMLAnchorElement) => {
    anchor.addEventListener('click', this.handleAnchorClick)
  })
}
Run Code Online (Sandbox Code Playgroud)

带有演示的 StackBlitz


注意 请就您更喜欢哪种解决方案以及原因发表评论,实际上我很难选择我更喜欢哪种解决方案。


hzi*_*oun 7

这可能为时已晚,但让我希望能帮助某人.

由于您需要单击绑定(可能还有其他绑定),最好跳过使用 [innerHTML]="..."创建通过@Input()注释向其传递数据的内部组件.

具体来说,图像中有一个名为BaseComponent的组件,您可以在其中将一些HTML代码设置为变量htmlData :

let htmlData  = '...<button (click)="yourMethodThatWontBeCalled()">Action</button>...'
Run Code Online (Sandbox Code Playgroud)

然后在BaseComponent的html文件中绑定它,如下所示:

...<div [innerHTML]="htmlData"></div>...
Run Code Online (Sandbox Code Playgroud)

而不是这样做,你创建InnerComponent.ts:

@Component({
 selector: 'inner-component',
 templateUrl: './inner-component.html',
 styleUrls: ['./inner-component.scss']
})
export class InnerComponent {
   @Input()
   inputData: any;

   methodThatWillBeCalled(){
    //do you logic on this.inputData
   }
}
Run Code Online (Sandbox Code Playgroud)

InnerComponent的Html文件:

...<button (click)="methodThatWillBeCalled()">Action</button>...
Run Code Online (Sandbox Code Playgroud)

现在在BaseComponent的Html文件中:

...<inner-component [inputData]="PUT_HERE_YOUR_DATA"></inner-component>
Run Code Online (Sandbox Code Playgroud)

  • 添加子组件并输入经过净化的或简单的 html 后,这对我不起作用。 (2认同)
  • @Mitchapp 这导致了我的问题的解决,谢谢。 (2认同)