When handling a document click event in Typescript, an error may occur where it cannot read

Just starting out with Typescript and diving into Angular, I am currently in the process of converting my project to the Angular system. However, I've hit a roadblock. I need to figure out how to close the dropdown content when the user clicks anywhere except the dropdown button. Any help for this beginner would be greatly appreciated. I've been searching online but haven't found a solution yet. Thanks in advance!

DETAILS

These are from the app.component

app.component.html

<section class="nav">
  <div class="one-side-nav">
      <a href="#" routerLink = "/"><img id="logo" src="assets/img/logoheaven.png"></a>
      <a href="#" routerLink = "/catalog" id="framed">SOMETHING</a>
  </div>
  <div class="one-side-nav">
      <a href="">SOMTHING</a>
      <a href="">SOMETHING</a>
      <a href=""><img src="assets/img/lists/notification.png"></a>
      <div class="dropdown">
          <img (click)="dropdown()" class="dropdown-btn" id = "dropdown-btn" src="assets/img/defaultimg.png">
          <div id="dropdown-content" class="dropdown-content">
              <div class="box-head-blue"></div>
              <a href="#">dropdown</a>
              <a href="#">dropdown</a>
              <a href="#">dropdown</a>
              <button style="border-radius: 0px 0px 10px 10px" id="logout-btn">dropdown</button>
          </div>
      </div>
  </div>
</section>

app.component.ts

import { Component, HostListener } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

//COMPONENT LOGIC
export class AppComponent {
  title = 'SPARK | Trang Chủ';

  dropdown() {
    document.getElementById("dropdown-content").classList.toggle("show");
  }

  @HostListener('document:click', ['$events'])
  onDocumentClick(event: MouseEvent) {
    if (!(event.target == document.getElementById("dropdown-btn"))) {
      var dropdown = document.getElementById("dropdown-content");
      if (dropdown.classList.contains("show")) {
          dropdown.classList.remove("show");
      }
    }
  }

}

ERROR IM GETTING

ERROR TypeError: Cannot read property 'target' of undefined
    at AppComponent.onDocumentClick (app.component.ts:19)
    at AppComponent_click_HostBindingHandler (app.component.ts:10)
    at executeListenerWithErrorHandling (core.js:21815)
    at wrapListenerIn_markDirtyAndPreventDefault (core.js:21857)
    at HTMLDocument.<anonymous> (platform-browser.js:976)
    at ZoneDelegate.invokeTask (zone-evergreen.js:399)
    at Object.onInvokeTask (core.js:41640)
    at ZoneDelegate.invokeTask (zone-evergreen.js:398)
    at Zone.runTask (zone-evergreen.js:167)
    at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:480)

HOW I HAVE IT IN JAVASCRIPT (works)

function dropdown() {
    document.getElementById("dropdown-content").classList.toggle("show");
}

window.onclick = function(e) {
    if (!e.target.matches(".dropdown-btn")) {
        var dropdown = document.getElementById("dropdown-content");
        if (dropdown.classList.contains("show")) {
            dropdown.classList.remove("show");
        }
    }
}

Answer №1

Ensure to use $event instead of $events.

Consider the following solution:

 @HostListener('document:click', ['$event'])
  onDocumentClick(event: MouseEvent) {
    if (!(event.target == document.getElementById("dropdown-btn"))) {
      var dropdown = document.getElementById("dropdown-content");
      if (dropdown.classList.contains("show")) {
          dropdown.classList.remove("show");
      }
    }
  }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Callbacks for AJAX responses that are asynchronous

After using AJAX in a limited and straightforward manner for some time, I find myself currently debugging a web application that heavily relies on JavaScript and JQuery for client-side coding. One issue that has caught my attention is the possibility of mu ...

Choose the key value from a deep object structure

I'm facing a dilemma. Within the layers of this object, I need to identify and select a specific key among the nested elements. The structure of the object is as follows: var x={ "_shards": { "total": 10, "successful": 5, ...

Activate hover effect on toggle button

When I hover over the "CHANGE" button, the orange color appears as expected. Clicking the button once turns the color red but removes the hover color, which is fine. However, clicking it twice brings back the original blue color but the hover effect is m ...

Creating a list in an Angular class: A step-by-step guide

In my Angular class, I have set up the username and password fields. Now, I want to include a list of roles as well. How can I go about adding this list of roles? export class User { userid: number; username: string; password: string; ro ...

Using Vuejs 2 to manage assets

As a beginner in VueJS, I am exploring ways to incorporate an external JavaScript library into my component. After downloading the minified JS file and placing it in my assets directory, I'm unsure how to compile my component to utilize this library ...

Issues with NgRx testing - NullInjectorError: Service provider not found

When attempting to write unit tests for effects, I encountered the error NullInjectorError: No provider for StationsListService!. The code in my stations.effects.ts file looks like this: @Injectable() export class StationsListEffects { constructor(priva ...

Trigger a jQuery event when a different selection is made in the dropdown menu

There are 2 choices available in the dropdown menu. <select id="_fid_140" onchange="chooseRecordPicker()" > <option value="736">9000000146</option> <option value="x3recpcker#">&lt; Browse choices... &gt;</option> Upo ...

Having Trouble Assigning a Value to a Dropdown Menu in AngularJS

I am working with a DropDown feature where I am using ng-repeat to bind values to the options. My goal is to set the selected value based on the 'value' field only. Below is the code snippet: <div ng-controller="myCtrl"> <select ng ...

Is there an easier method to utilize ES6's property shorthand when passing an object in TypeScript, without needing to prefix arguments with interface names?

When working with JavaScript, I often find myself writing functions like the one below to utilize ES6's property shorthand feature: function exampleFunction({param1, param2}) { console.log(param1 + " " + param2); } //Usage: const param1 = "param1" ...

The appearance of the pop-up mask is displayed at lightning speed

Check out the demo here Here is the HTML code: <div class="x"> </div> <input class="clickMe" type="button" value="ClickMe"></input> This is the JS code: $(".clickMe").click( function() { ...

Animate moving between two points over a set period using JavaScript

My attempt to smoothly move a box from one position to another using Linear Interpolation is not working as expected. The box just moves without any easing effect. I came across a post on Stack Overflow titled C# Lerping from position to position, but I ma ...

Creating a quiz with just one question in React: A step-by-step guide

How can I add the functionality to handle correct and incorrect answers? I've designed a single-question quiz with multiple options. The Quiz component has been created. See the code snippet below: Quiz Component export default function Quiz(props) { ...

Combining JSON parameter and multipart/form-data file in a single request using Vue.js

Is there a way to send both JSON parameters and multipart/form-data files in a single request using Vue, similar to how Postman does it? https://i.sstatic.net/CMi3D.png I've been looking into how to submit "multipart/form-data" from VueJs. What I nee ...

My presentations are not functioning as expected, could there be a problem with my HTML, CSS, or JavaScript coding?

My website utilizes a Slideshow feature to display images for blog posts. Recently, I attempted to include multiple slideshows within an article, which unfortunately caused all of the slideshows to malfunction. As it stands now, when the code is executed, ...

Attempting to discover the secret to keeping a hamburger menu fixed in place once it has been expanded

Exploring this example https:// codepen.io/ducktectiveQuack/pen/mPGMRZ I had trouble understanding the code block, so I resorted to trickery (just remove the space between the '/' and the 'c' lol) My goal is to have the hamburger men ...

The CORS policy is causing a blockage for the front-end application due to the Spring Boot backend

Currently working with Spring Boot and Angular. I have included the cross-origin annotation in my code to allow access from my Angular localhost port, but unfortunately, I am still encountering the following error: https://i.sstatic.net/4uDuv.png Here is ...

An innovative way to display or hide a div depending on the multiple selections made in a select2 jQuery field

A select2 jQuery dropdown menu is set up with two options: *For Rent *For Sales If the user selects 'For Rent', specific fields will be displayed below it, as well as for 'For Sales'. The challenge arises when both options are ...

Customize the position of the Datetimepicker

Is there a way to customize the position of the datetimepicker, ensuring that it stays within the visual boundaries without getting cut off? I need help with this. ...

Transforming a THREE.js shader into a PIXI.js shader

I am currently exploring the world of PIXI.js and custom Shaders, and I must admit, it's a bit overwhelming for me. I came across a GLSL Shader (created by DonKarlssonSan) that I would like to convert to PIXI.js in order to compare performance. Any as ...

Effective techniques for unit testing in Vue.js

Here's a question that's been on my mind: when it comes to unit testing in Vue.js, there are several different packages available. Vue Test Utils Vue Jest Vue Cypress For enterprise projects, which of these options would be considered best ...