1

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) ;
    } 

  }
3
  • Any reason on why you would use an object tag instead of a svg one ? Commented Nov 5, 2018 at 10:47
  • I use object to load an external svg depending on the status of an object Commented Nov 5, 2018 at 10:51
  • You can use the svg tag to do that. Any other reason ? Commented Nov 5, 2018 at 10:53

2 Answers 2

1

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);
    });
  }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, but i have an error with undefined nativeElement
You mean that this example doesn't work for you ? What browser are you using ?
It works, with the listener only on nativeElement : sasensi-svg-element-creation-ejdmfy.stackblitz.io
Another question, is angular managing the graphic event (click) of part of SVG ?
I think you should ask this as a separated question.
0

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;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.