1/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16import {Component, EventEmitter, Input, Output} from '@angular/core';
17import {MatSelectChange} from '@angular/material/select';
18
19@Component({
20  selector: 'select-with-filter',
21  template: `
22    <mat-form-field appearance="fill" [style]="getOuterFormFieldStyle()">
23      <mat-label>{{ label }}</mat-label>
24      <mat-select
25        (opened)="filter.focus()"
26        (closed)="onSelectClosed()"
27        (selectionChange)="onSelectChange($event)"
28        [multiple]="multiple"
29        [value]="value">
30        <mat-form-field class="select-filter" [style]="getInnerFormFieldStyle()">
31          <mat-label>Filter options</mat-label>
32          <input matInput #filter [(ngModel)]="filterString" />
33        </mat-form-field>
34        <mat-option
35          *ngFor="let option of options"
36          [value]="option"
37          [class.hidden-option]="!option.includes(filterString)">
38          {{ option }}
39        </mat-option>
40      </mat-select>
41    </mat-form-field>
42  `,
43  styles: [
44    `
45      mat-form-field {
46        width: 100%;
47        font-size: 12px;
48      }
49
50      .hidden-option {
51        display: none;
52      }
53    `,
54  ],
55})
56export class SelectWithFilterComponent {
57  @Input() label: string = '';
58  @Input() options: string[] = [];
59  @Input() outerFilterWidth = '75';
60  @Input() innerFilterWidth = '100';
61  @Input() flex = 'none';
62  @Input() multiple = true;
63  @Input() value?: string | string[] | undefined;
64
65  @Output() readonly selectChange = new EventEmitter<MatSelectChange>();
66
67  filterString: string = '';
68
69  onSelectChange(event: MatSelectChange) {
70    this.selectChange.emit(event);
71  }
72
73  getOuterFormFieldStyle() {
74    return {
75      flex: this.flex,
76      width: this.outerFilterWidth + 'px',
77    };
78  }
79
80  getInnerFormFieldStyle() {
81    return {
82      flex: 'none',
83      paddingTop: '2px',
84      paddingLeft: '10px',
85      paddingRight: '20px',
86      width: this.innerFilterWidth + 'px',
87    };
88  }
89
90  onSelectClosed() {
91    this.filterString = '';
92  }
93}
94