64

The common approaching to use canvas in javascript is like :

var canvas = document.getElementById('tutorial');
var ctx = canvas.getContext('2d');

but in Angular2 I cannot get the HTMLCanvasElement object, the var "canvas" only get the HTMLElement in Angular2. So how to use canvas in Angular2? And furthermore, how to use the third-party javascript in Angular2 with the language TypeScript?

realappie
  • 4,656
  • 2
  • 29
  • 38
stephzcj
  • 695
  • 1
  • 6
  • 9

2 Answers2

143

You can accomplish this by using @ViewChild

In your class do the following.

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

@Component({
   name: 'my-component',
   // notice the variable name myCanvas
   template: `<canvas #myCanvas></canvas>`
})
export class myComponent implements AfterViewInit {
  // its important myCanvas matches the variable name in the template
  @ViewChild('myCanvas')
  canvas: ElementRef<HTMLCanvasElement>;

  context: CanvasRenderingContext2D;

  ngAfterViewInit(): void {
    this.context = this.canvas.nativeElement.getContext('2d');
  }
}

Try to stay away from using document as much as you can, as it could bite you on the long run. Also using @ViewChild has an advantage over querying the DOM, once the application is compiled. Angular already knows ahead of time which element it needs to do the modifications on, rather than having to find it in the DOM.

For a full example check out this demo


Update

For angular 8 you need to use ViewChild like this.

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

See How should I use the new static option for @ViewChild in Angular 8? for more information

realappie
  • 4,656
  • 2
  • 29
  • 38
  • 2
    ur right, thanks. but it seems use "var ctx = this.canvas.nativeElement.getContext("2d");" : ) – stephzcj Jun 08 '17 at 08:27
  • I get 'getContext does not exist on ElementRef' – Joe Oct 26 '17 at 05:08
  • 1
    @joe its funny how the accepted answer has a subtle mistake, its `myCanvas.nativeElement.getContext` – realappie Oct 26 '17 at 06:27
  • Thanks. I had switched the type to HTMLCanvasElement, but that didn't work either. I'm now successfully rendering! – Joe Oct 26 '17 at 10:40
  • @Joe For more type information checkout the updated answer :) Nobody likes to search canvas methods when we are using typescript! – realappie Oct 26 '17 at 12:16
  • @Abdel, thank you. I'm really new to Angular and don't really see the JS/typescript bridge when coding, only in transpiling. – Joe Oct 26 '17 at 15:52
  • @joe what editor are you using? If you use vscode or sublime text with a typescript plugin your life will become so much easier! – realappie Oct 26 '17 at 15:54
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/157590/discussion-between-joe-and-abdel). – Joe Oct 26 '17 at 16:01
  • This answer helped me a lot. Angular8 requires a second parameter for the decorator. Here's what it should look like now: @ViewChild('myCanvas', {static:false}) myCanvas: ElementRef; – raddevus Jul 10 '19 at 12:15
  • 1
    @raddevus Added a note for angular 8, thanks for bringing this to my attention :D – realappie Jul 11 '19 at 07:15
  • Hi! I followed this recommendation but I'm keep getting "Cannot read property 'nativeElement' of undefined TypeError: Cannot read property 'nativeElement' of undefined" . Do you guys have any ideas why is that? – alex Aug 04 '20 at 12:55
  • 1
    @Alexandra I think you probably figured it out by now but that means the reference to the canvas element is either incorrect, or the canvas element is not present at the time the `ngAfterViewInit` is called. This could be the case if its wrapped in for example an `*ngIf` which is false at that moment. – realappie Aug 11 '20 at 10:54
  • Yes, indeed, you a right, it was wrapped around a *ngIf. I figured it out in the end, but thanks a lot for your reply. I really appreciate it. – alex Aug 11 '20 at 11:38
4

This works for me in Angular 13

@ViewChild('myCanvas')
private myCanvas: ElementRef = {} as ElementRef;

I've tried realappie's solution but it was still showing me an error