typescript viewChild 如何获取在angular2 中使用js 添加的元素?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37421007/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:31:30  来源:igfitidea点击:

How viewChild can get elements that added with js in angular2?

typescriptangulardatatablesviewchild

提问by MortezaDalil

If a HTML element has been added to the DOM(for example after click on button), How can we access this element? viewChild can't see that.

如果 HTML 元素已添加到 DOM(例如单击按钮后),我们如何访问该元素?viewChild 看不到那个。

Update 1:More description

更新 1:更多说明

I've used jquery datatable (jquery.dataTables definitelyTyped version). Base on thislink, I can add new column and define html inside that. I wrote this code :

我使用过 jquery 数据表(jquery.dataTables 绝对类型化版本)。基于链接,我可以添加新列并在其中定义 html。我写了这段代码:

           columnDefs: [
                    {
                        render: function (data, type, row) {
                            return `
                                  <a href="admin/edituser/` + row.UserId+ `" class="btn btn-outline btn-circle btn-sm green"><i class="fa fa-edit" > </i> Edit </a>`+
                                 `<a [routerLink]="['Delete']" class="btn btn-outline btn-circle btn-sm red"><i class="fa fa-trash-o" > </i> Delete </a>
                                            `;
                        },
                        targets: 5
                    },
                ],

enter image description here

在此处输入图片说明

With Chrome Developer tools I see this : enter image description here

使用 Chrome 开发人员工具,我看到了这一点: 在此处输入图片说明

First anchor tag works but with href, not routerLink.

第一个锚标记有效,但使用 href,而不是 routerLink。

Second anchor tag doesn't work because angular directives didn't complie to href.

第二个锚标记不起作用,因为角度指令不符合 href。

I tried to use DynamicComponentLoader to compile it, and changed code like this: enter image description here

我尝试使用 DynamicComponentLoader 来编译它,并更改如下代码: 在此处输入图片说明

But I can't access #target element with viewChild.(I want to change it with another component by loadNextToLocation). I think this isn't optimize way to get good result.

但是我无法使用 viewChild 访问 #target 元素。(我想通过 loadNextToLocation 用另一个组件更改它)。我认为这不是获得良好结果的优化方法。

I want to use routerLink with commands buttons inside jquery datatable.

我想在 jquery 数据表中使用带有命令按钮的 routerLink。

Could you please help me in the right direction to solve this?

你能帮我朝着正确的方向解决这个问题吗?

Thank you in advance.

先感谢您。

solution :

解决方案 :

If you want to add HTML to DOM with javascript or some callback function first determine a tag from template that can be a parent for those element(s) in future.

如果您想使用 javascript 或某些回调函数将 HTML 添加到 DOM,请首先从模板中确定一个标记,该标记将来可以成为这些元素的父级。

  1. Add template variable to this parent element.(#target for example)

                    <th> Email</th>
                    <th> Date </th>
                    <th> Phone </th>
                    <th> Commands</th>
    
    
                </tr>
            </thead>
            <tbody #target></tbody>
            <tfoot>
                <tr>
    
                    <th>  </th>
                    <th>  </th>
                    <th>  </th>
                    <th>  </th>
    
                </tr>
            </tfoot>
        </table>
    
  2. Then add a simple class and a simple attribute to your html code(This code is generated after page compiled with angular,Also you can write some code with typescript or javascript to generate html).

       columnDefs: [
                    {
                        render: function (data, type, row) {
                            return `
                                 `<a date-id="` + row.UserId + `" class="editbtn btn btn-outline btn-circle btn-sm red"> Edit</a>
                                 `;
                        },
                        targets: 5
                    },
                ],
    
  3. Now import and inject these sources to your component:

        import {ViewChild, Renderer} from '@angular/core';
    

    and :

        constructor(private renderer: Renderer, private router: Router)
    
  4. Define a viewChild variable in your component class:

        @ViewChild('target') target;
    
  5. Write a function like this :

    public AfterEverything() {
           var el: HTMLElement = this.target.nativeElement;//Make an Element Object
           console.log(el);
           var commands: NodeListOf<Element> = el.getElementsByClassName('editbtn');//Find Element Object to get all elements with a specefic class
           console.log(commands);
           for (var i = 0; i < commands.length; i++) {
               //Loop for add event or style
               console.log(commands[i]);
               //Sample event(Click for routing)
               this.renderer.listen(commands[i], 'click', (event: Event) => {
                   var thisid = event.srcElement.getAttribute("date-id");//Get value from element
                   console.log(thisid);
                   this.router.parent.navigate(['EditUser', { id: thisid }]);//Use value to make routeLink
                   console.log(event.srcElement.innerHTML);
               });
               this.renderer.setElementStyle(commands[i], 'backgroundColor', 'yellow');//for change color(just sample)
           }
    

    }

  6. You must find best place to call this function,for example, ajax data callback is one choice and call AfterEverything() inside that. You can call this function inside ngAfterViewInit().

  1. 将模板变量添加到此父元素。(例如#target)

                    <th> Email</th>
                    <th> Date </th>
                    <th> Phone </th>
                    <th> Commands</th>
    
    
                </tr>
            </thead>
            <tbody #target></tbody>
            <tfoot>
                <tr>
    
                    <th>  </th>
                    <th>  </th>
                    <th>  </th>
                    <th>  </th>
    
                </tr>
            </tfoot>
        </table>
    
  2. 然后在你的html代码中添加一个简单的类和一个简单的属性(这段代码是用angular编译页面后生成的,你也可以用typescript或javascript编写一些代码来生成html)。

       columnDefs: [
                    {
                        render: function (data, type, row) {
                            return `
                                 `<a date-id="` + row.UserId + `" class="editbtn btn btn-outline btn-circle btn-sm red"> Edit</a>
                                 `;
                        },
                        targets: 5
                    },
                ],
    
  3. 现在将这些源导入并注入到您的组件中:

        import {ViewChild, Renderer} from '@angular/core';
    

    和 :

        constructor(private renderer: Renderer, private router: Router)
    
  4. 在组件类中定义一个 viewChild 变量:

        @ViewChild('target') target;
    
  5. 写一个这样的函数:

    public AfterEverything() {
           var el: HTMLElement = this.target.nativeElement;//Make an Element Object
           console.log(el);
           var commands: NodeListOf<Element> = el.getElementsByClassName('editbtn');//Find Element Object to get all elements with a specefic class
           console.log(commands);
           for (var i = 0; i < commands.length; i++) {
               //Loop for add event or style
               console.log(commands[i]);
               //Sample event(Click for routing)
               this.renderer.listen(commands[i], 'click', (event: Event) => {
                   var thisid = event.srcElement.getAttribute("date-id");//Get value from element
                   console.log(thisid);
                   this.router.parent.navigate(['EditUser', { id: thisid }]);//Use value to make routeLink
                   console.log(event.srcElement.innerHTML);
               });
               this.renderer.setElementStyle(commands[i], 'backgroundColor', 'yellow');//for change color(just sample)
           }
    

    }

  6. 您必须找到调用此函数的最佳位置,例如,ajax 数据回调是一种选择,并在其中调用 AfterEverything()。你可以在 ngAfterViewInit() 中调用这个函数。

Note that sometimes a delay of several seconds is necessary to ensure that all new elements are created.

请注意,有时需要延迟几秒钟以确保创建所有新元素。

回答by Günter Z?chbauer

If you add HTML dynamically (like [innerHTML]="someHtml"), then you can use direct DOM access (frowned upon in Angular2) by injecting ElementRefand using ElementRef.nativeElement.querySelector...

如果您动态添加 HTML(如[innerHTML]="someHtml"),那么您可以通过注入ElementRef和使用来使用直接 DOM 访问(在 Angular2 中不受欢迎)ElementRef.nativeElement.querySelector...

If the HTML is generated using *ngForyou can add template variables and query for these elements like

如果 HTML 是使用生成的,*ngFor您可以添加模板变量并查询这些元素,例如

<div *ngFor="let x of y" #someVar></div>

and then in the component class

然后在组件类中

@ViewChildren('someVar') elements;

ngAfterViewInit() {
  console.log(this.elements);
}