Как 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 или какой-либо функции обратного вызова, сначала определите тег из шаблона, который может быть родительским для этих элементов в будущем.
Добавьте переменную шаблона к этому родительскому элементу (например, # 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>
Затем добавьте простой класс и простой атрибут в ваш 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 }, ],
Теперь импортируйте и вставьте эти источники в ваш компонент:
import {ViewChild, Renderer} from '@angular/core';
а также:
constructor(private renderer: Renderer, private router: Router)
Определите переменную viewChild в классе вашего компонента:
@ViewChild('target') target;
Напишите такую функцию:
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) }
}
Вы должны найти лучшее место для вызова этой функции, например, обратный вызов данных 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);
}