Как получить доступ к элементу HTML из директивы атрибута Angular?
Документы Angular предоставляют пример для создания директивы атрибута, которая изменяет цвет фона элемента:
https://angular.io/docs/ts/latest/guide/attribute-directives.html
<p myHighlight>Highlight me!</p>
import { Directive, ElementRef } from '@angular/core';
@Directive({ selector: '[myHighlight]' })
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
}
Могу ли я также использовать el.nativeElement
чтобы получить содержимое элемента (например, " Highlight me!
), Изменить его и обновить элемент?
Ответы
Ответ 1
Итак, мой комментарий, который вы должны сделать console.log(el.nativeElement)
, должен был указать вам в правильном направлении, но я не ожидал, что вывод будет просто строкой, представляющей DOM Element
.
Что вам нужно сделать, чтобы проверить его так, как оно помогает вам в вашей проблеме, - это сделать console.log(el)
в вашем примере, тогда у вас будет доступ к объекту nativeElement
и вы увидите свойство, называемое innerHTML
.
Что приведет к ответу на ваш оригинальный вопрос:
let myCurrentContent:string = el.nativeElement.innerHTML; // get the content of your element
el.nativeElement.innerHTML = 'my new content'; // set content of your element
Обновление для лучшего подхода:
Так как принятый ответ и веб-работники становятся все более важными день ото дня (и в любом случае это считается лучшей практикой), я хочу добавить здесь это предложение Марка Райкока.
Лучший способ манипулировать программным обеспечением DOM Elements
- это Renderer:
constructor(private _elemRef: ElementRef, private _renderer: Renderer) {
this._renderer.setElementProperty(this._elemRef.nativeElement, 'innerHTML', 'my new content');
}
Изменить
Так как Renderer
устарел, используйте Renderer2 вместо setProperty
Обновление:
Этот вопрос с его ответом объяснил поведение console.log
.
Это означает, что console.dir(el.nativeElement)
будет более прямым способом доступа к DOM Element
как "проверяемому" объекту в вашей консоли для этой ситуации.
Надеюсь, что это помогло.
Ответ 2
Я предлагаю использовать Render, поскольку документация по ElementRef API предлагает:
... взгляните на Renderer, который предоставляет API, который можно безопасно использовать, даже если прямой доступ к собственным элементам не поддерживается. Использование прямого доступа к DOM создает тесную связь между вашим приложением и уровнями рендеринга, что делает невозможным их разделение и развертывание приложения в веб-приложении или Universal.
Всегда используйте Renderer, потому что он сделает ваш код (или нужную вам библиотеку) способным работать при использовании Universal или WebWorkers.
import { Directive, ElementRef, HostListener, Input, Renderer } from '@angular/core';
export class HighlightDirective {
constructor(el: ElementRef, renderer: Renderer) {
renderer.setElementProperty(el.nativeElement, 'innerHTML', 'some new value');
}
}
Не похоже, что в Render есть метод getElementProperty(), поэтому, я думаю, нам все еще нужно использовать NativeElement для этой части. Или (лучше) передать содержимое в качестве входного свойства в директиву.
Ответ 3
Это связано с тем, что содержимое
<p myHighlight>Highlight me!</p>
не отображается при создании конструктора HighlightDirective, так что пока нет содержимого.
Если вы реализуете AfterContentInit, вы получите элемент и его содержимое.
import { Directive, ElementRef, AfterContentInit } from '@angular/core';
@Directive({ selector: '[myHighlight]' })
export class HighlightDirective {
constructor(private el: ElementRef) {
//el.nativeElement.style.backgroundColor = 'yellow';
}
ngAfterContentInit(){
//you can get to the element content here
//this.el.nativeElement
}
}
Ответ 4
Основываясь на ответе @Mark, я добавляю конструктор в директиву, и он работает со мной.
Я делюсь образцом, к которому относятся.
constructor(private el: ElementRef, private renderer: Renderer) {
}
Файл TS
@Directive({ selector: '[accordion]' })
export class AccordionDirective {
constructor(private el: ElementRef, private renderer: Renderer) {
}
@HostListener('click', ['$event']) onClick($event) {
console.info($event);
this.el.nativeElement.classList.toggle('is-open');
var content = this.el.nativeElement.nextElementSibling;
if (content.style.maxHeight) {
// accordion is currently open, so close it
content.style.maxHeight = null;
} else {
// accordion is currently closed, so open it
content.style.maxHeight = content.scrollHeight + "px";
}
}
}
HTML
<button accordion class="accordion">Accordian #1</button>
<div class="accordion-content">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quas deleniti molestias necessitatibus quaerat quos incidunt! Quas officiis repellat dolore omnis nihil quo,
ratione cupiditate! Sed, deleniti, recusandae! Animi, sapiente, nostrum?
</p>
</div>
Демонстрация https://stackblitz.com/edit/angular-directive-accordion?file=src/app/app.component.ts