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