Подтвердить что ты не робот

Как получить доступ к элементу 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!), Изменить его и обновить элемент?

4b9b3361

Ответ 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