0

I'm trying to transfer a dropdown menu from Javascript to Typescript to use in my Angular project. I can't figure out how to simulate event.target.matches though, which is giving me some problems. Is there a Typescript equivalent that is easy to implement?

Here's the component code:

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
  title = 'Test Site Please Ignore';
  currentUser: any;

  ngOnInit(){
    this.currentUser=JSON.parse(localStorage.getItem("currentUser"));
  }
  dropfunction(variable){
    var dropdowns=document.getElementsByClassName("dropdown-content");
    var i;
    for (i = 0; i < dropdowns.length; i++) {
      var openDropdown = dropdowns[i];
      if (openDropdown.classList.contains('show')) {
          openDropdown.classList.remove('show');
      }
    }
    var thisElement=document.getElementById(variable);
    thisElement.classList.toggle("show");
  };
  onClickedOutside(e: Event) {
    if (!e.target.matches('.dropbtn')){
      var dropdowns = document.getElementsByClassName("dropdown-content");
      var i;
      for (i = 0; i < dropdowns.length; i++) {
          var openDropdown = dropdowns[i];
          if (openDropdown.classList.contains('show')) {
              openDropdown.classList.remove('show');
          }
      }
    }
  }
}

Which gives me the error: "[ts] Property 'matches' does not exist on type 'EventTarget'." (triggered by the if statement of onClickedOutside.

Edit, the template code:

<div class="dropdown">
<button (clickOutside)="onClickedOutside($event)" (click)="dropfunction('myDropdown0')" id="dropbtn0" class="dropbtn">Home</button>
<div id="myDropdown0" class="dropdown-content">
    <a routerLink="/"> Index </a>
    <a routerLink="/profile">Profile</a>
    <div *ngIf="currentUser">
      <a routerLink="/login">Logout</a>
    </div>
    <div *ngIf="!currentUser">
      <a routerLink="/login">Login</a>
      <a routerLink="/register">Register</a>
    </div>
</div>

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Marcus Grass
  • 1,043
  • 2
  • 17
  • 38

3 Answers3

2

Maybe you're using an old version of TypeScript The matches methods on elements is implemented in the newer versions of TypeScript. You can see this github thread that referenced the issue.

To solve it:

  • Update to the latest version of TypeScript

Or

  • You can change your condition with matches and use classList.contains() instead.
 if(!e.target.classList.contains('dropbtn'))
edkeveked
  • 17,989
  • 10
  • 55
  • 93
  • 1
    I'm using version 2.7.2, I think i must be doing something else wrong here, I'll add the template code in an edit, maybe the problem lies there. Because I can't add .classList to it either. – Marcus Grass Jun 09 '18 at 21:36
  • A little bit of a nitpick here, you don't want the `.` that denotes a class here, you'd want just `dropbtn` inside your contains check for an element that has a class of `dropbtn`. – Jeph Nov 26 '18 at 21:12
0

Try to use

if( !e.target.value === '.dropbtn')

instead.

0

Solved it with the help of this post. Had to set event.target to an element.

Working:

onClickedOutside(e: Event) {
var ele=<Element>e.target;
if (!ele.matches('.dropbtn')){
  var dropdowns = document.getElementsByClassName("dropdown-content");
  var i;
  for (i = 0; i < dropdowns.length; i++) {
      var openDropdown = dropdowns[i];
      if (openDropdown.classList.contains('show')) {
          openDropdown.classList.remove('show');
      }
  }
}

}

Marcus Grass
  • 1,043
  • 2
  • 17
  • 38