Javascript 角度及;TailwindCSS-下拉菜单

Javascript 角度及;TailwindCSS-下拉菜单,javascript,angular,drop-down-menu,dropdown,tailwind-css,Javascript,Angular,Drop Down Menu,Dropdown,Tailwind Css,如果之前有人回答过,我深表歉意,但我已经搜索了几天来寻找答案,但我还没有找到一个对我的设置有意义的解决方案(也许我的设置是错误的,让我们找出答案) 我想使用Angular和Tailwind CSS创建一个下拉菜单,我的组件html如下所示: // recipe-details.component.html <div> <div *ngIf="selectedRecipe;else noRecipe"> <div class="

如果之前有人回答过,我深表歉意,但我已经搜索了几天来寻找答案,但我还没有找到一个对我的设置有意义的解决方案(也许我的设置是错误的,让我们找出答案)

我想使用Angular和Tailwind CSS创建一个下拉菜单,我的组件html如下所示:

// recipe-details.component.html
<div>
  <div *ngIf="selectedRecipe;else noRecipe">
    <div class="flex items-center justify-between">
      <h3 class="text-title">{{ selectedRecipe.name }}</h3>

      <!-- The dropdown menu -->
      <div class="relative">

        <!-- The dropdown button -->
        <a href="#" class="bg-green-500 px-3 py-2 rounded-md shadow font-bold text-white flex items-center" appDropdown>Manage recipe
          <svg class="w-5 h-5 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"
            xmlns="http://www.w3.org/2000/svg">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
          </svg></a>

          <!-- Dropdown list of links -->
          <div class="origin-top-right absolute right-0 w-full rounded mt-2 shadow-lg border-gray-800">
            <div class="bg-white py-2">
              <a href="#" class="block px-4 py-2 font-bold text-sm text-gray-700 hover:bg-gray-100">Edit Recipe</a>
              <a href="#" class="block px-4 py-2 font-bold text-sm text-gray-700 hover:bg-gray-100">Delete Recipe</a>
            </div>
          </div>

      </div>

    </div>
    <p>{{ selectedRecipe.description }}</p>
  </div>

  <ng-template #noRecipe>
    <div class="">
      <div class="text-title ">Choose a recipe</div>
      <p>Please choose a recipe from the recipe list.</p>
    </div>
  </ng-template>
</div>
//recipe-details.component.html
{{selectedRecipe.name}
{{selectedRecipe.description}

选择食谱 请从配方列表中选择一个配方

对于菜单按钮,我已使用选择器appDropdown创建了一个指令:

//dropdown.directive.ts
从“@angular/core”导入{指令、EventEmitter、HostListener、输出};
@指示({
选择器:“[appDropdown]”
})
导出类下拉指令{
@Output()isMenuOpen=新的EventEmitter();
等参:布尔=假;
构造函数(){}
@HostListener(“单击”)切换菜单(){
this.isOpen=!this.isOpen;
this.isMenuOpen.emit(this.isOpen);
log(`Menu status changed.Menu现在是${this.isOpen?'Open':'Closed'}`)
}
}
如果我目前的想法有道理的话,在另一个指令中处理EventEmitter并将其放在links div的下拉列表中是否更有意义。该指令将使用HostBinding应用css将div的不透明度设置在
opacity-0
opacity-100
之间,无论
isOpen
真还是

如果这种方法有效,我不确定如何在第二个指令中侦听第一个指令中的事件

如果我完全偏离了目标,有没有人能提供一个解决方案来帮助我理解工作流程


谢谢

我想这样写问题有助于我找到解决办法。如果有人有办法改进我的代码,请随时发布其他方法:)

我的解决方案:

//recipe-detail.component.html
<div>
  <div *ngIf="selectedRecipe;else noRecipe">
    <div class="flex items-center justify-between">
      <h3 class="text-title">{{ selectedRecipe.name }}</h3>
      <div class="relative">
        <a href="#" class="bg-green-500 px-3 py-2 rounded-md shadow font-bold text-white flex items-center" (isMenuOpen)=toggleVisible($event) appDropdown>Manage recipe
          <svg class="w-5 h-5 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"
            xmlns="http://www.w3.org/2000/svg">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
          </svg></a>
          <div class="origin-top-right absolute right-0 w-full rounded mt-2 shadow-lg border-gray-800" [ngClass]="visibilityClasses">
            <div class="bg-white py-2">
              <a href="#" class="block px-4 py-2 font-bold text-sm text-gray-700 hover:bg-gray-100">Edit Recipe</a>
              <a href="#" class="block px-4 py-2 font-bold text-sm text-gray-700 hover:bg-gray-100">Delete Recipe</a>
            </div>
          </div>
      </div>
    </div>
    <p>{{ selectedRecipe.description }}</p>
  </div>

  <ng-template #noRecipe>
    <div class="">
      <div class="text-title ">Choose a recipe</div>
      <p>Please choose a recipe from the recipe list.</p>
    </div>
  </ng-template>
</div>
//dropdown.directive.ts
从“@angular/core”导入{指令、EventEmitter、HostListener、输出};
@指示({
选择器:“[appDropdown]”
})
导出类下拉指令{
@Output()isMenuOpen=新的EventEmitter();
等参:布尔=假;
构造函数(){}
@HostListener(“单击”)切换菜单(){
this.isOpen=!this.isOpen;
this.isMenuOpen.emit(this.isOpen);
log(`Menu status changed.Menu现在是${this.isOpen?'Open':'Closed'}`)
}
}
//recipe-detail.component.html
<div>
  <div *ngIf="selectedRecipe;else noRecipe">
    <div class="flex items-center justify-between">
      <h3 class="text-title">{{ selectedRecipe.name }}</h3>
      <div class="relative">
        <a href="#" class="bg-green-500 px-3 py-2 rounded-md shadow font-bold text-white flex items-center" (isMenuOpen)=toggleVisible($event) appDropdown>Manage recipe
          <svg class="w-5 h-5 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"
            xmlns="http://www.w3.org/2000/svg">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
          </svg></a>
          <div class="origin-top-right absolute right-0 w-full rounded mt-2 shadow-lg border-gray-800" [ngClass]="visibilityClasses">
            <div class="bg-white py-2">
              <a href="#" class="block px-4 py-2 font-bold text-sm text-gray-700 hover:bg-gray-100">Edit Recipe</a>
              <a href="#" class="block px-4 py-2 font-bold text-sm text-gray-700 hover:bg-gray-100">Delete Recipe</a>
            </div>
          </div>
      </div>
    </div>
    <p>{{ selectedRecipe.description }}</p>
  </div>

  <ng-template #noRecipe>
    <div class="">
      <div class="text-title ">Choose a recipe</div>
      <p>Please choose a recipe from the recipe list.</p>
    </div>
  </ng-template>
</div>
//recipe-detail.component.ts
import { Component, OnInit } from '@angular/core';
import { Recipe } from 'src/app/models/models.i';
import { RecipeService } from '../../../services/recipes/recipe.service'

@Component({
  selector: 'app-recipe-detail',
  templateUrl: './recipe-detail.component.html',
  styleUrls: ['./recipe-detail.component.scss']
})
export class RecipeDetailComponent implements OnInit {
  selectedRecipe: Recipe;
  visibilityClasses: {};
  private isVisible: boolean = false;

  constructor(private recipeService: RecipeService) { }

  ngOnInit(): void {
    this.recipeService.currentRecipe.subscribe(recipe => this.selectedRecipe = recipe
    );
    this.setVisibilityClasses();
  }

  toggleVisible(isVisible: boolean): void {
    console.log(`is the menu open: ${isVisible ? 'Yes' : 'No'}`)
    this.isVisible = isVisible;
    this.setVisibilityClasses();
  }

  private setVisibilityClasses(): void {
    this.visibilityClasses = {
      'opacity-0': !this.isVisible,
      'opacity-100': this.isVisible
    };
  }
}
//dropdown.directive.ts
import { Directive, EventEmitter, HostListener, Output } from '@angular/core';

@Directive({
  selector: '[appDropdown]'
})
export class DropdownDirective {
  @Output() isMenuOpen = new EventEmitter<boolean>();
  isOpen: boolean = false;

  constructor() { }

  @HostListener('click') toggleMenu() {
    this.isOpen = !this.isOpen;
    this.isMenuOpen.emit(this.isOpen);
    console.log(`Menu status changed. Menu is now ${this.isOpen ? 'Open' : 'Closed'}`)
  }
}