Как 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.

Второй тег привязки не работает, потому что директивы angular не соответствуют 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 ().

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


person MortezaDalil    schedule 24.05.2016    source источник
comment
Как это добавить?   -  person Günter Zöchbauer    schedule 24.05.2016
comment
Например, см. Это: datatables.net/examples/advanced_init/column_render.html. Мы можем использовать функцию рендеринга, чтобы добавить текст (например, HTML) внутри столбца. Представьте, что мы хотим изменить элементы, созданные с помощью этой функции.   -  person MortezaDalil    schedule 24.05.2016
comment
Решение, которое вы добавили к своему ответу, в основном такое же, как то, которое я объяснил с помощью ElementRef. Вы начинаете не с основного элемента компонентов, а с более конкретного элемента, как описано в stackoverflow.com/questions/32693061/   -  person Günter Zöchbauer    schedule 25.05.2016


Ответы (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);
}
person Günter Zöchbauer    schedule 24.05.2016
comment
Спасибо, но я не смог решить свою проблему. Я добавил в свой вопрос более подробную информацию. - person MortezaDalil; 25.05.2016
comment
Переменные шаблона не работают, когда HTML добавляется динамически. Ваш вопрос не показывает, как добавлен HTML. Вам нужно использовать подход ElementRef. - person Günter Zöchbauer; 25.05.2016
comment
Я нашел решение и добавил его к своему вопросу. - person MortezaDalil; 25.05.2016