简体   繁体   中英

How to destroy a VexFlow renderer from an Angular component?

In an Angular application, I'm creating a VexFlow renderer:

ngAfterViewInit() {
  this.createSheet();
}
private createSheet() {
  if (this.soundtrack != null) {
    if (this.soundtrack.hasNotes()) {
      this.sheetService.createSoundtrackSheet(this.name, this.soundtrack);
    }
  }
}

using the service method:

private VF = vexflow.Flow;
private renderContext(name: string, width: number, height: number) {
  const elementName = ELEMENT_PREFIX + name;
  const element = document.getElementById(elementName);
  const renderer = new this.VF.Renderer(element, this.VF.Renderer.Backends.SVG);
  renderer.resize(width, height);
  return renderer.getContext();
}

I'm passing a DOM reference document.getElementById(elementName); to the renderer constructor.

Should I do some freeing in the ngOnDestroy() component method ?

UPDATE: This is how the actual full component looks like:

export class SheetComponent implements OnInit, AfterViewInit {

  @Input() soundtrack: Soundtrack;
  @Input() device: Device;
  name: string;

  constructor(
    private sheetService: SheetService
  ) { }

  ngOnInit() {
    this.initializeName();
  }

  ngAfterViewInit() {
    this.createSheet();
  }

  private initializeName() {
    if (this.soundtrack != null) {
      this.name = NAME_PREFIX_SOUNDTRACK + this.soundtrack.name;
    } else if (this.device != null) {
      this.name = NAME_PREFIX_DEVICE + this.device.name;
    }
  }

  private createSheet() {
    if (this.soundtrack != null) {
      if (this.soundtrack.hasNotes()) {
        this.sheetService.createSoundtrackSheet(this.name, this.soundtrack);
      }
    } else if (this.device != null) {
      this.sheetService.createDeviceSheet(this.name, this.device);
    }
  }

}

with the template:

<div id="{{name}}"></div>

Now, maybe there's a way to use a @ViewChild(name) name: ElementRef; annotation, but this doesn't compile:

export class SheetComponent implements OnInit, AfterViewInit {

  @Input() soundtrack: Soundtrack;
  @Input() device: Device;
  name: string;
  @ViewChild(name) sheetElement: ElementRef;

  constructor(
    private sheetService: SheetService
  ) { }

  ngOnInit() {
    this.initializeName();
  }

  ngAfterViewInit() {
    this.createSheet();
  }

  private initializeName() {
    if (this.soundtrack != null) {
      this.name = NAME_PREFIX_SOUNDTRACK + this.soundtrack.name;
    } else if (this.device != null) {
      this.name = NAME_PREFIX_DEVICE + this.device.name;
    }
  }

  private createSheet() {
    if (this.soundtrack != null) {
      if (this.soundtrack.hasNotes()) {
        this.sheetService.createSoundtrackSheet(this.sheetElement.nativeElement.id, this.soundtrack);
        // this.soundtrackStore.setSoundtrackSheet(this.name, sheet); TODO
      }
    } else if (this.device != null) {
      this.sheetService.createDeviceSheet(this.sheetElement.nativeElement.id, this.device);
      // this.deviceStore.setDeviceSheet(this.name, sheet); TODO
    }
  }

}

No. You don't have to do anything to remove DOM elements from the view.

When the component is destroyed all the children of the parent DOM elements are also destroyed. Including DOM event listeners attached to this elements.

You should use a view query like @ViewChild to access the DOM element and pass it to the function. Instead of querying the document directly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM