0

How do we listen for click events on SVG path or g elements with Angular?

In this demo if a (click) event binding is added to the svg elements the click() event handler fires. How do we get it to work for path or g svg elements?

The end goal is to add a class to the path when the user clicks on it.

Ole
  • 41,793
  • 59
  • 191
  • 359
  • 1
    You example seems to work just fine. I see `DING DONG ` in the console. It's a bit hard to click, though, as the stroke-width is so small and there is no fill. – qrsngky Mar 06 '23 at 04:45
  • OH ... OK ... We have to click on the stroke exactly ... I thought we could click anywhere within the element... – Ole Mar 06 '23 at 04:49
  • OK ... In that case I have to update the question a bit ... I need the event to fire also if the inside of the path is clicked ... so where the `fill` area is ... – Ole Mar 06 '23 at 04:51
  • 1
    If you use `pointer-events: all` css property, it will react to the click event even if the 'fill' is 'none'. However, you can't see exactly which parts are sensitive. Another alternative is using `fill: rgba(0,0,0,0)`. Same problem with not knowing exactly where the sensitive part is. – qrsngky Mar 06 '23 at 04:51
  • AWESOME!! @qrsngky thanks and if you want to give an official answer I can accept it. – Ole Mar 06 '23 at 04:53
  • The thing is, I wonder if there's a duplicate. This one seems similar enough (if one reads the title, but then the content seems too different): https://stackoverflow.com/questions/22418341/how-to-make-transparent-part-of-svg-clickable – qrsngky Mar 06 '23 at 04:56
  • Well this is an Angular context, but it's completely up to you. Personally I feel like context based answers are better. – Ole Mar 06 '23 at 04:57
  • ... and questions with inline code snippets, your stackblitz will be gone at sometime. [How to add a StackOverflow snippet](https://meta.stackoverflow.com/questions/269753/feedback-requested-runnable-code-snippets-in-questions-and-answers) – Danny '365CSI' Engelman Mar 06 '23 at 07:55
  • Since you want to click anywhere in the fill, why is having the handler on `` no good? Seems to behave the way you specify. – Charles.de.Pierrefonds Mar 06 '23 at 09:31
  • @Charles.de.Pierrefonds the fill area of the path element is not the entire svg, though; if you change the fill to something visible then you'll see the difference. – qrsngky Mar 07 '23 at 06:09

1 Answers1

1

The OP's demo showed a correct example of listening for click events on an SVG element with Angular. To simplify a bit, the main.html file can be as follows:

<svg width="500" height="500" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <path 
     (click)="click($event)"
      style="fill: none; stroke: #000000; stroke-width: 1px;"
      d="M 10.280374,48.130842 V 26.168224 H 52.336448 V 70.794392 H 26.869158 V 50 h -7.476635"
    />
</svg>

I'll also copy OP's code for main.ts from StackBlitz so that other people can test it in the future:

import 'zone.js/dist/zone';
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';

@Component({
  selector: 'my-app',
  standalone: true,
  imports: [CommonModule],
  templateUrl: `./main.html`,
})
export class App {
  name = 'Angular';
  click(e: MouseEvent) {
    console.log('DING DONG', e.target);
  }
}

bootstrapApplication(App);

The above will work with e.target pointing to the correct path element.

The actual cause of "element's fill area not clickable" is something else. Since there is no fill (due to the CSS property fill:none), by default you can only click on the stroke. And when the stroke is thin, it's hard to click the element.

If you don't have to support old browsers, the solution is by adding a css property pointer-events: all to the path element. (For more info about this property, see https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events )

To support older browsers, you can use fill: rgba(0,0,0,0) or fill: transparent, or any fill color with fill-opacity: 0. This is less performant, though, as a browser may still try to paint a 'transparent color' over the background in those regions (although the result is exactly the same not painting over the background, it's like multiplying by 1 and adding by 0)

qrsngky
  • 2,263
  • 2
  • 13
  • 10