Как viewChild может получить элементы, которые были добавлены с помощью js в angular2?

Если HTML-элемент был добавлен в DOM(например, после нажатия кнопки), как мы можем получить доступ к этому элементу? viewChild этого не видит.

Обновление 1: более подробное описание

Я использовал jquery datatable ( 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
                    },
                ],

С помощью инструментов разработчика Chrome я вижу это:

Первый тег привязки работает, но с помощью href, а не routerLink.

Второй тег привязки не работает, потому что угловые директивы не соответствуют href.

Я попытался использовать DynamicComponentLoader для его компиляции и изменил код следующим образом:

Но я не могу получить доступ к элементу #target с помощью viewChild. (Я хочу изменить его с помощью другого компонента с помощью loadNextToLocation). Я думаю, что это не оптимизированный способ получить хороший результат.

Я хочу использовать routerLink с кнопками команд внутри jquery datatable.

Не могли бы вы помочь мне в правильном направлении, чтобы решить эту проблему?

Заранее спасибо.

решение:

Если вы хотите добавить HTML в DOM с помощью javascript или какой-либо функции обратного вызова, сначала определите тег из шаблона, который может быть родительским для этих элементов в будущем.

  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. Также вы можете написать некоторый код с машинописью или 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().

Обратите внимание, что иногда требуется задержка в несколько секунд, чтобы обеспечить создание всех новых элементов.

1 ответ

Если вы добавляете HTML динамически (например, [innerHTML]="someHtml"), то вы можете использовать прямой доступ к DOM (хмурится в Angular2), введя ElementRef и используя ElementRef.nativeElement.querySelector...

Если HTML генерируется с помощью *ngFor Вы можете добавить переменные шаблона и запросить эти элементы, такие как

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

а затем в классе компонентов

@ViewChildren('someVar') elements;

ngAfterViewInit() {
  console.log(this.elements);
}
Другие вопросы по тегам