aurny2420289
aurny2420289

Reputation: 491

Access dom element in angular 6

In a component, i have an svg rendering inside template and would manipulate it in order to put some graphics. Actually, i can't access svg Document with nativeElement or HTMLElement.

template is :

     template:

     `<div>
           <object data="/assets/deploiement.svg" type="image/svg+xml" height="450" width="650" #dataSvg >
              </object>
</div>`,

exemple i want to implement :

    ngAfterViewInit() {

  const elemnentRef = this.dataSvg;
  console.log(elemnentRef.);
   const circle = '<circle cx="500" cy="50" r="65" />';

 ( this.state === 2 ) {
      this.dataSvg.nativeElement.svg.append(circle) ;
    } 

  }

Upvotes: 1

Views: 6050

Answers (2)

Rami Alloush
Rami Alloush

Reputation: 2626

I turns out, the best way is to access it from the constructor

waitingControlLoad : boolean = true;

constructor(
    private _elementRef: ElementRef,
) { }

Then, try to access from ngAfterContentChecked as follows

ngAfterContentChecked() {
    // getElementsByClassName('form-control') is readOnly (not Live)
    // querySelector gets Live element but only first one!
    // querySelectorAll gets static Nodelist (readOnly)
    const list = this._elementRef.nativeElement.getElementsByTagName('input');
    if (this.waitingControlLoad && list.length > 0) {
        for (const item of list) {
            item.type = 'search';
        }
        // Prevent further invokations
        this.waitingControlLoad = false;
    }
}

Upvotes: 0

sasensi
sasensi

Reputation: 4650

The problem you are encountering is related to the fact that you are using object element which is made to manage external ressources and creates a "sub-window" (like iframe does).
So if you really want to keep this approach, the only way you have to manipulate the content loaded through <option> is to wait for the content to be loaded and target <svg> element inside the sub-window.
Note that due to CORS restrictions, this will only work if the content you load comes from the same server as your page.

Here is a simple Stackblitz example demonstrating the solution.

import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <div>
      <object data="/assets/debug.svg" type="image/svg+xml" height="450" width="650" #dataSvg></object>
    </div>
  `,
})
export class AppComponent implements AfterViewInit {
  @ViewChild('dataSvg') dataSvg: ElementRef;

  ngAfterViewInit() {
    const elemnentRef = this.dataSvg;
    // when content is loaded...
    elemnentRef.nativeElement.contentWindow.addEventListener('load', function (event) {
      // ...retrieve svg element
      const document = elemnentRef.nativeElement.contentWindow.document;
      const svg = document.querySelector('svg');
      // create a circle
      const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
      circle.setAttributeNS(null, 'cx', 50);
      circle.setAttributeNS(null, 'cy', 50);
      circle.setAttributeNS(null, 'r', 40);
      circle.setAttributeNS(null, 'fill', 'red');
      // append it to existing content
      svg.append(circle);
    });
  }
}

Upvotes: 1

Related Questions