Добавить класс к ссылке при нажатии на нее и удалить его при нажатии в другом месте - PullRequest
0 голосов
/ 27 мая 2020

Важно : я пробовал много решений, и ни одно из них не помогло мне.

У меня есть раскрывающийся список, я хочу добавить его CSS класс, когда я наводил или щелкал по нему, и удалял его, когда щелкал где-то еще.

a.linkOnMouseDropDown:hover /*work fine */
{
  background-color: rgb(220, 234, 255) !important;
  color: rgb(21, 96, 143);
  cursor: pointer;
}

a.linkOnMouseDropDown:focus /*not work*/
{
  background-color: rgb(220, 234, 255);
  color: rgb(21, 96, 143);
}

a.linkOnMouseDropDown:not(:focus) /*not work */
{
  background-color: transparent;
  color: white;
}

a.dropDownOption:hover //work fine
{
  background-color: rgb(25, 99, 112) !important;
  cursor: pointer;
}
<ul class=" nav navbar-nav navbar-right">
  <li appDropdown>
    <a class="dropdown-toggle linkOnMouseDropDown" role="button">Manage <span class="caret"></span></a>
    <ul class="dropdown-menu">
      <li><a class="dropDownOption">Save Data</a></li>
      <li><a class="dropDownOption">Fetch Data</a></li>
    </ul>
  </li>
</ul>

Опять же: мне нужно, чтобы раскрывающийся список «Управление» был изменен, когда пользователь наводит курсор или щелкает по нему в соответствии с:

   a.linkOnMouseDropDown:hover

И удаляю, когда щелкаю где-нибудь еще.

Большое спасибо! :)

Ответы [ 3 ]

1 голос
/ 27 мая 2020

Чтобы динамически назначать класс CSS на основе событий click и blur способом Angular, вы можете использовать ElementRef со ссылочной переменной шаблона. Попробуйте следующий

Шаблон

<ul class="nav navbar-nav navbar-right" appDropDown #r="appDropDown" >
  <button #manageButton type="button" class="btn btn-primary dropdown-toggle custom-button" data-toggle="dropdown" >
    Manage
    <span class="caret"></span></button>
  <ul class="dropdown-menu" [ngClass]="{'show':r.isOpen}" >
    <li><a class="dropdown-item" href="#">Save Data</a></li>
    <li><a class="dropdown-item" href="#">Fetch Data</a></li>
  </ul>
</ul>

Здесь #manageButton - это ссылочная переменная шаблона.

Контроллер

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent {
  @ViewChild('manageButton') manageButton: any; 

  constructor(private _el: ElementRef) { }

  ngAfterViewInit() {
    this.manageButton.nativeElement.addEventListener('click', this.onClick.bind(this));
    this.manageButton.nativeElement.addEventListener('blur', this.onBlur.bind(this));
  }

  onClick() {
    this.manageButton.nativeElement.classList.add('custom-background')
  }

  onBlur() {
    this.manageButton.nativeElement.classList.remove('custom-background')
  }
}

CSS

.custom-background {
  background-color: rgb(220, 234, 255) !important;
  color:rgb(21, 96, 143) ;
}

.custom-button:hover {
  background-color: rgb(220, 234, 255) !important;
  color:rgb(21, 96, 143) ;
}

Рабочий пример: Stackblitz

1 голос
/ 29 мая 2020

Я решил проблему, это основано на моей собственной директиве (Angular):

@Directive({
    selector:'[appDropdown]'
})
export class DropdownDirective {
    @HostBinding('class.open') isOpen = false;
    @HostListener('document:click', ['$event']) toggleOpen(event: Event) 
    {
      this.isOpen = this.elRef.nativeElement.contains(event.target) ? !this.isOpen : false; 
      this.headerservice.isDropdownOpen.next(this.isOpen); //I added this line!

    }
    constructor(private elRef: ElementRef,
                private headerservice: HeaderService) {}  
}

И моем классе обслуживания:

export class HeaderService{

    isDropdownOpen = new Subject<boolean>();
}

Я использую флаг, но я тоже надо все время его слушать, поэтому добавил тему в Сервис. Теперь я слушаю его в компоненте заголовка:

export class headerComponent implements OnInit,OnDestroy{
    collapsed = true;
    linkPressed = "";
    subscription: Subscription;
    dropdownClicked=false;

    constructor(private headerservice: HeaderService){}

    ngOnInit(): void {
      this.subscription = this.headerservice.isDropdownOpen.subscribe(
        (state: boolean) =>{
          this.dropdownClicked = state;
      }
      );

    }
    ngOnDestroy(): void {
      this.subscription.unsubscribe();
    }
}


<ul class=" nav navbar-nav navbar-right ">
            <li class="" appDropdown>
                <a  class="dropdown-toggle linkOnMouseHover" [ngClass]="{customBackground:dropdownClicked}" role="button">Manage <span class="caret"></span></a>
                <ul class="dropdown-menu">
                    <li><a  class="dropDownOption" >Save Data</a></li>
                    <li><a  class="dropDownOption" >Fetch Data</a></li>
                </ul>
            </li>
        </ul>

Заключение: мне пришлось использовать свой флаг директивы. Однако в компоненте заголовка есть другой подход, как предложил Майкл Д. (вместо использования ngClass):

@ViewChild('manageButton', {static: false}) manageButton: any; 

И в функции подписки:

if(state == true){
       this.manageButton.nativeElement.classList.add('customBackground');
}else{
       this.manageButton.nativeElement.classList.remove('customBackground');
}
1 голос
/ 27 мая 2020

Если вы хотите прослушивать оба события hover и click, вы не можете сделать это с помощью одного CSS, и для этой цели вам следует использовать javascript.

Допустим, у вас есть <a> с существующим классом linkOnMouseDropDown, поэтому всякий раз, когда кто-то наводит курсор на него или щелкает по нему, вам нужен новый класс для него. Вы можете обрабатывать часть hover только с CSS следующим образом:

.linkOnMouseDropDown:hover {
  color: red;
}

Но для части click вы должны добавить новый прослушиватель событий для click и всякий раз, когда целевой элемент содержит linkOnMouseDropDown мы добавляем к нему новый класс с именем newClass.

document.addEventListener('click', function (e) {
  if (e.target.classList.contains('linkOnMouseDropDown')) {
    e.target.classList.add('newClass');
  } else {
    document.querySelector('.linkOnMouseDropDown').classList.remove('newClass');
  }
})

Итак, ваш окончательный код должен быть примерно таким:

function addOrRemoveClass(e) {
  if (e.target.classList.contains('linkOnMouseDropDown')) {
    e.target.classList.add('newClass');
  } else {
    document.querySelector('.linkOnMouseDropDown').classList.remove('newClass');
  }
}
document.addEventListener('click', addOrRemoveClass)
.linkOnMouseDropDown:hover, .newClass {
  color: red;
}
<ul class=" nav navbar-nav navbar-right">
  <li appDropdown>
    <a class="dropdown-toggle linkOnMouseDropDown" role="button">Manage <span class="caret"></span></a>
    <ul class="dropdown-menu">
      <li><a class="dropDownOption">Save Data</a></li>
      <li><a class="dropDownOption">Fetch Data</a></li>
    </ul>
  </li>
</ul>

ОБНОВЛЕНИЕ

Поскольку вам нужно машинописное решение для этого, вам просто нужно обработать ввод параметров для вашей функции.

Так что вам просто нужно заменить часть js на это:

function addOrRemoveClass(e: any): void {
  if (e.target.classList.contains('linkOnMouseDropDown')) {
    e.target.classList.add('newClass');
  } else {
    document.querySelector('.linkOnMouseDropDown')?.classList.remove('newClass');
  }
}

document.addEventListener('click', addOrRemoveClass)

Рабочая демонстрация: codepen.io

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...