32

I have an Angular 1.x directive that appends an element. In short:

app.directive('mydirective', function() {
  template: '<ng-transclude></ng-transclude>',
  link: function(el) {
    var child = angular.element("<div/>");
    el.append(child);
  }

I can migrate this directive to Angular 2 like this:

@Directive({
  selector: '[mydirective']
})
export class MyDirective implements OnInit {
  constructor(private elementRef: ElementRef) { }

  ngOnit() {
    var child = angular.element("<div/>");
    this.elementRef.nativeElement.append(child);
  }
}

What's troubling me is this remark in the nativeElement official documentation:

Use this API as the last resource when direct access to DOM is needed.

My question is - how could I properly migrate this directive to Angular 2? My only requirement is to build an element dynamically and append it to the element with the directive.

Mycah
  • 4,602
  • 5
  • 24
  • 32
user11081980
  • 3,059
  • 4
  • 30
  • 48

1 Answers1

45

Use Renderer provided by Angular to manipulate the DOM:

import { DOCUMENT } from '@angular/common';

export class MyDirective implements OnInit {
  constructor(
    private elementRef: ElementRef,
    private renderer: Renderer2,
    @Inject(DOCUMENT) private document: Document) { }

  ngOnInit() {
    const child = this.document.createElement('div');
    this.renderer.appendChild(this.elementRef.nativeElement, child);
  }
}

This doesn't depend on the native DOM API like appendChild(), so in a way it's a platform-independent approach.

Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203
Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
  • isn't it wrong to create an attribute directive to add/remove elements to DOM? shouldn't we create structural directive instead? I have created a [question](https://stackoverflow.com/q/52074619/1822974) on that too – JPS Aug 29 '18 at 10:26
  • @DRB, yes, you should use structural directives. I described the approach in the article [Working with DOM in Angular: unexpected consequences and optimization techniques](https://blog.angularindepth.com/working-with-dom-in-angular-unexpected-consequences-and-optimization-techniques-682ac09f6866) – Max Koretskyi Aug 29 '18 at 16:24
  • What does`@Inject(DOCUMENT) private document` accomplish? – Oussama Essamadi May 06 '21 at 11:38
  • Injects `document` in a platform independent way, depending on how the platform defines `document` – Max Koretskyi May 06 '21 at 11:51
  • 3
    Here's the fixed link for [Working with DOM in Angular: unexpected consequences and optimization techniques](https://indepth.dev/posts/1134/working-with-dom-in-angular-unexpected-consequences-and-optimization-techniques). – Kirk Larkin Jul 29 '21 at 10:35