如何从Angular属性指令中访问元素HTML?

时间:2016-06-23 22:03:08

标签: 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!),修改此内容并更新元素吗?

4 个答案:

答案 0 :(得分:24)

实际上,我应该做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

更新以获得更好的方法:

由于这是公认的答案,网络工作者日常变得越来越重要(无论如何这被认为是最佳实践)我想在这里添加Mark Rajcok的这个建议。

以编程方式操作DOM Elements的最佳方法是使用Renderer

constructor(private _elemRef: ElementRef, private _renderer: Renderer) { 
    this._renderer.setElementProperty(this._elemRef.nativeElement, 'innerHTML', 'my new content');
}

修改

由于现在不推荐使用Renderer,请使用Renderer2代替setProperty

更新

This question with its answer解释了console.log行为。

这意味着,对于这种情况, console.dir(el.nativeElement) 将是您在控制台中作为“可检查”对象访问DOM Element的更直接方式。

希望这会有所帮助。

答案 1 :(得分:10)

我建议使用Render,因为ElementRef API doc建议:

  

...看看Renderer,它提供了可以安全使用的API,即使不支持直接访问本机元素也是如此。   依靠直接DOM访问会在您的应用程序和渲染层之间创建紧密耦合,这将使得无法将您的应用程序分离并将您的应用程序部署到Web worker或Universal

始终使用渲染器,因为它会使您在使用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。或者(更好)将内容作为输入属性传递给指令。

答案 2 :(得分:5)

这是因为

的内容
var array1 = [{ address: "www.example.com", hits: 1 }, { address: "www.anotherone.org", hits: 10 }],
    array2 = [{ address: "www.example.com", buttons: 1 }, { address: "www.yetanotherone.info", buttons: 2 }],
    array3 = [{ address: "www.example.com", cons: 1 }, { address: "andevenonemore.com", cons: 1 }],
    grouped = [];

[].concat(array1, array2, array3).forEach(function (a) {
    if (!this[a.address]) {
        this[a.address] = { address: a.address, hits: 0, buttons: 0, cons: 0 };
        grouped.push(this[a.address]);
    }
    Object.keys(a).forEach(function (k) {
        if (k !== 'address') {
            this[a.address][k] += a[k];
        }
    }, this);

}, Object.create(null));

console.log(grouped);
调用HighlightDirective的构造函数时,

尚未呈现,因此尚无内容。

如果您实施AfterContentInit挂钩,您将获得该元素及其内容。

<p myHighlight>Highlight me!</p>

答案 3 :(得分:0)

基于@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