1

I have an issue with a click event handler not firing when its containing div was originally hidden, then later displayed. The code below is Angular, but I am uncertain if this is an Angular issue.

ParentComponent.ts

@Component({
   selector: "parent",
   template: `
      <div (click)="showChildren()">Click Here!</div>
      <div class="container">
         <ng-content>
      </div>
   `,
   styles: [`
      .container {
         display: none;
      }
      .show .container {
         display: block;
      }
   `]
})
export class ParentComponent {
   @HostBinding("class.show") show = false;
   showChildren(): void {
      this.show = true;
   }
}

ChildComponent.ts:

@Component({
   selector: "child",
   template: "<ng-content>"
})
export class ChildComponent.ts {
   @HostListener("click")
   clickMe(): void {
      /* This event is never captured */
   }
}

Usage:

<parent>
   <child>Child 1</child>
   <child>Child 2</child>
   <child>Child 3</child>
</parent>

Rendered Output:

<parent>
   <div (click)="showChildren()">Click Here!</div>
   <div class="container">
      <child (click)="clickMe()">Child 1</child>
      <child (click)="clickMe()">Child 2</child>
      <child (click)="clickMe()">Child 3</child>
   </div>
</parent>

Here is what is happening:

  1. When the page first renders, the div with the "container" class is initially hidden because display is set to none
  2. Next, the user clicks on "Click Here!" and the class "show" is added to the parent div. This changes display on the container to block.

Everything works properly up to here. The container div is rendered the child elements are displayed.

Here is the problem: The click handlers on the child elements do not fire. If the child elements are originally shown with display: block;, the click handlers work properly. It's only when the containing div is first hidden and later displayed that they do not work.

Any idea why? Any help is appreciated.

1 Answer 1

0

The class show is added to the host element child, but we are looking for the first element in the child HTML with .show class if you see the selector .show .container.

Since we are adding to the host element <child>, we should use the :host selector to indicate that the show will be present in the host element which is child selector.

Before:

 .container {
    display: none;
 }
 .show .container {
    display: block;
 }

After:

 .container {
    display: none;
 }
 :host.show .container { /* changed here! */
    display: block;
 }

Full Code:

import { Component, HostBinding, HostListener } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';

@Component({
  selector: 'child',
  standalone: true,
  template: '<ng-content/>',
})
export class ChildComponent {
  @HostListener('click')
  clickMe(): void {
    alert('click');
  }
}

@Component({
  selector: 'parent',
  standalone: true,
  template: `
  {{show}}
    <div (click)="showChildren()">Click Here!</div>
    <div class="container">
        <ng-content/>
    </div>
  `,
  styles: [
    `
    .container {
        display: none;
    }
    :host.show .container {
        display: block;
    }
  `,
  ],
})
export class ParentComponent {
  @HostBinding('class.show') show = false;
  showChildren(): void {
    this.show = true;
  }
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [ParentComponent, ChildComponent],
  template: `
    <parent>
      <child>Child 1</child>
      <child>Child 2</child>
      <child>Child 3</child>
    </parent>
  `,
})
export class App {}

bootstrapApplication(App);

Stackblitz Demo

Sign up to request clarification or add additional context in comments.

10 Comments

This is incorrect. The class show is added the parent element and the container is properly displayed. Recall from the question... This is not a problem with displaying an element. The problem is that the click handlers do not fire. When is the container is displayed with display:block on initial render, the click handlers work. It is only when it is first display:none then later changed that the click handlers do not fire
@user2977624 please fix my stackblitz so that the issue happens there and share back, need exact working scenario
@user2977624 If you add Hostbinding on the parent it will add the class to the host element which is parent, that is how angular works.
@user2977624 I hide and show the element, but the click handler works -> stackblitz
I found the problem. The click handler I was using to display the container was on the parent element and not the div with the Click Me text. The clicks were never making it through to the child elements. Thank you again for your help.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.