角度下拉过滤器 - 按钮

问题描述 投票:0回答:1

我需要使用 Mat-Select 指令的下拉过滤器由按钮而不是输入字段调用和显示。另外,我想隐藏输入字段,以便只有按钮可见,从而调用过滤器,就像可以在 Azure DevOps 门户中找到的以下过滤器一样:

Azure DevOps Example

它必须是一个 CDK 覆盖面板,因为我不希望每当打开过滤器时屏幕的内容都会发生变化。

我尝试将 Mat-Select 与编程代码结合使用来模拟打开和关闭 Mat-Select 下拉列表。当输入字段隐藏时,这不起作用,即使打开和关闭它,它仍然保持隐藏状态。

我也尝试过仅隐藏 Mat-Select 指令的某些方面,但由于某种原因,CSS 样式没有生效。

我已经达到了下面的效果,剩下要做的就是隐藏右侧输入,单击按钮时,下拉菜单需要出现在按钮下方:

Current Filter State.

顺便说一句,所有这些过滤器选项都是动态的,并且作为可重用组件的一部分,可以注入到任何其他 HTML 中,并且只要提供特定的配置,它就会生成并发出过滤器。

下面是该组件的 HTML 和 TS 代码示例:

HTML:

<mat-card class="reusable-filter-mat-card">
    <mat-card-content *ngIf="dropDownFilterConfig || checkBoxFilterConfig" class="parent-filter-style">
        <ng-container *ngFor="let checkbox of checkBoxFilterConfig.config">
          <button mat-button (click)="toggleCheckBox()">
            <mat-icon class="material-symbols-outlined">instant_mix</mat-icon>
            {{checkbox.title}}
          </button>
          <mat-form-field>
            <mat-select mat-button [(value)]="selectedCheckbox" multiple hidden="true" #checkBoxFilter>
              <ng-container *ngFor="let option of checkbox.data">
                <mat-option [value]="option" (click)="onSelectCheckbox(option)">
                  <div *ngIf="checkbox.displayProperty; else stringProperty">
                    {{option[checkbox.displayProperty]}}
                  </div>
                  <ng-template #stringProperty>
                    {{option}}
                  </ng-template>
                </mat-option>
              </ng-container>
            </mat-select>
          </mat-form-field>
        </ng-container>
    </mat-card-content>
</mat-card>

TS:

import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
import { CheckBoxFilterConfig, DropDownFilterConfig, FilterOutput } from './reusable-filter.interface';
import { MatSelect } from '@angular/material/select';

@Component({
  selector: 'reusable-filter',
  templateUrl: './reusable-filter.component.html',
  styleUrls: ['./reusable-filter.component.scss']
})
export class ReusableFilterComponent implements OnInit {
  // Input and Output
  @Input() dropDownFilterConfig!        : DropDownFilterConfig
  @Input() checkBoxFilterConfig!        : CheckBoxFilterConfig
  @ViewChild(MatSelect) checkBoxFilter! : MatSelect;
  @Output() FilterOutput                = new EventEmitter<any>();

  // Class Variables
  isCheckBoxFilterOpen = false
  isDropDownFilterOpen = false
  selectedDropDown!: any
  selectedCheckbox: any[] = []
  appliedFilters: FilterOutput = {
    dropDownFilter: [],
    checkBoxFilter: []
  }

  ngOnInit(): void {
    this.dropDownFilterConfig = {
      enabled : true,
      config  : [
      {
        title : 'Personnel Filter',
        data  : [
        {
          name: 'John Kinsington',
          title: 'Infrastructure Engineer'
        },
        {
          name: 'Susan Burlsworth',
          title: 'Infrastructure Engineer'
        },
        {
          name: 'Macy McCready',
          title: 'Infrastructure Engineer'
        },
        {
          name: 'Mike Rinsworth',
          title: 'Infrastructure Engineer'
        }],
        displayProperty: 'name'
      }]
    }

    this.checkBoxFilterConfig = {
      enabled : true,
      config  : [
      {
        title : 'Video Games',
        data  : [
        {
          name: 'Call of Duty',
          rating: 5
        },
        {
          name: 'Satisfactoy',
          rating: 8.5
        },
        {
          name: 'Dota 2',
          rating: 9
        },
        {
          name: 'Medal of Honour',
          rating: 7.2
        }],
        displayProperty: 'name'
      }]
    }

  }

  onSelectDropdown(event: any){
    console.log(event)
    this.appliedFilters.dropDownFilter = event
    console.log(this.appliedFilters)
    this.isDropDownFilterOpen = !this.isDropDownFilterOpen
  }

  onSelectCheckbox(event: any){
    this.appliedFilters.checkBoxFilter = event
    console.log(this.appliedFilters)
  }

  toggleDropDown(){
    this.isDropDownFilterOpen = !this.isDropDownFilterOpen;
  }

  toggleCheckBox(){
    this.checkBoxFilter.toggle()
  }

  toggleOption(option: any) {
    if (this.isSelected(option)) {
      this.selectedCheckbox = this.selectedCheckbox.filter(selected => selected !== option);
    } else {
      this.selectedCheckbox.push(option);
    }
  }

  isSelected(option: any): boolean {
    return this.selectedCheckbox.includes(option);
  }

  emitSelectedFilters(){
    this.FilterOutput.emit(this.appliedFilters)
  }

}

任何想法或建议将不胜感激!

angular angular-material angular-filters viewchild mat-select
1个回答
0
投票

我看到您正在尝试创建由按钮触发的下拉过滤器,类似于您在 Azure DevOps 中看到的,同时保持输入字段隐藏。我在项目中也遇到过类似的需求,我想我可以帮助你。

首先,由于您希望通过按钮而不是通常的输入字段打开下拉菜单,因此您需要使用 Angular 的 ViewChild 以编程方式控制 mat-select 的打开。另外,要隐藏输入字段但保留功能,您可以使用一些 CSS 技巧。这里有一个方法:

HTML 更新:修改现有 HTML 以包含一个负责切换下拉列表的按钮。确保您的 mat-select 被模板变量引用,我们将在 TypeScript 文件中使用该变量。

<button mat-button (click)="toggleCheckBox()">{{checkbox.title}}</button>
<mat-form-field style="display:none;">
    <mat-select #checkBoxFilter>
        <!-- options go here -->
    </mat-select>
</mat-form-field>

组件逻辑:在组件中,使用 ViewChild 获取对 MatSelect 的引用。然后,您可以使用此引用以编程方式打开和关闭下拉菜单。

@ViewChild('checkBoxFilter') checkBoxFilter: MatSelect;

toggleCheckBox() {
    this.checkBoxFilter.toggle();
}

CSS 样式:为了确保只有按钮可见并且垫选择保持隐藏,请应用简单的 CSS 样式,例如 display: none;到 mat-form-field。

定位下拉菜单:既然您提到您不希望打开过滤器时屏幕内容发生变化,您可以考虑使用 Angular CDK 的 Overlay 面板来自定义下拉菜单的位置。这将允许您控制下拉菜单相对于按钮的显示位置。

通过这些步骤,单击按钮应切换下拉过滤器的可见性。此设置可确保实际的垫选择保持隐藏状态,不会影响您的布局,同时单击按钮时仍然有效。

我希望这有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.