Search code examples
htmlangulartypescriptgridster

How to access gridster using ElementRef's nativeElement


I'm encountering this issue only in Firefox browser, not in Chrome. I'm attempting to obtain the nativeElement for the gridster element.

I am using angular-gridster2 v17.0.0 In my HTML :

<gridster
        [options]="options"
        #gridsterContainer>
        <gridster-item
            *ngFor="let dis of displayList; let i = index"
            [item]="dis.layout">
            <dis-data></dis-data>
        </gridster-item>
    </gridster>

In my component, I've defined a ViewChild and trying to access nativeElement in my download event:

@ViewChild('gridsterContainer', { static: false }) gridsterContainer: ElementRef;

downloadPDF() {
  setTimeout(() => {
    const content = this.gridsterContainer.nativeElement;

    const marginHeight: number = 40;
    const width = content.clientWidth;
    const height = content.scrollHeight + marginHeight;
    let orientation: 'p' | 'portrait' | 'l' | 'landscape' = 'l';
    if (width > height) {
        orientation = 'l';
    } else {
        orientation = 'p';
    }
    domToImage.toPng(content, {
        width: width,
        height: height
    })
      .then((imageBase64) => {            
        const img = new Image();
        img.src = imageBase64;
        img.onload = () => {
            const cursorPositionX = 25;
            let cursorPositionY = 75;
            const jsPdfOptions: jsPDFOptions = {
                orientation: orientation,
                unit: 'pt',
                format: [width + 50, height + 220] 
            };
            const pdf = new jsPDF(jsPdfOptions);
            pdf.addImage(imageBase64, 'PNG', cursorPositionX, cursorPositionY += 20, width, height);
            pdf.save('Jack_Test.pdf');
        };
        img.onerror = (error) => {
          console.error('Error loading image:', error);
        };
      })
      .catch((error) => {
        console.error('Error converting to image:', error);
      });
    }, 10);
    
  }

However, content is showing as undefined. I've tried using ngAfterViewInit and document.querySelector('gridster') as well, but I'm unable to retrieve the nativeElement.


Solution

  • The issue occurs because gridsterContainer doesn't really contain an ElementRef. By default, @ViewChild() reads the instance of the Component. If it's not an Angular component but a native HTML element, Angular reads the ElementRef. However in this particular case, Angular will read the component instance by default, as <gridster> is an Angular component. To read the element ref, you need to tell Angular to do so by using the read parameter:

    @ViewChild('gridsterContainer', { read: ElementRef }) gridsterContainer: ElementRef;
    

    Unfortunately, Angular is not smart enough to warn you about the wrong type being used. This will likely be improved with the new signal-based queries, however as of July 2024 they are in developer preview and should be used with caution.

    Further reading: https://angular.dev/api/core/ViewChild?tab=description