ngx-column-filter-popup 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCUMENTATION.md +690 -0
- package/LICENSE +21 -0
- package/README.md +451 -0
- package/USAGE_EXAMPLES.md +251 -0
- package/package.json +86 -0
- package/src/app/components/column-filter/column-filter.component.html +131 -0
- package/src/app/components/column-filter/column-filter.component.scss +426 -0
- package/src/app/components/column-filter/column-filter.component.ts +445 -0
- package/src/app/components/column-filter/column-filter.module.ts +31 -0
- package/src/app/lib/models/filter.models.ts +51 -0
- package/src/app/lib/public-api.ts +21 -0
- package/src/app/lib/services/column-filter.service.ts +35 -0
- package/src/app/lib/utils/column-filter.utils.ts +236 -0
package/README.md
ADDED
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
# Column Filter Library
|
|
2
|
+
|
|
3
|
+
A powerful, reusable Angular column filter component with support for multiple field types, advanced filtering rules, and customizable match modes.
|
|
4
|
+
|
|
5
|
+
[](https://badge.fury.io/js/%40blumptech%2Fcolumn-filter)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- ✅ **Multiple Filter Rules**: Add multiple filter conditions per column
|
|
11
|
+
- ✅ **Multiple Field Types**: Specialized filters for different data types
|
|
12
|
+
- **Text** - Text fields (default)
|
|
13
|
+
- **Currency** - Currency values with symbol support
|
|
14
|
+
- **Age/Number** - Numeric values
|
|
15
|
+
- **Date** - Date values with date picker
|
|
16
|
+
- **Status** - Predefined status options dropdown
|
|
17
|
+
- ✅ **Global Match Mode**: Choose how to combine multiple rules
|
|
18
|
+
- **Match All Rules** (AND Logic): All rules must match
|
|
19
|
+
- **Match Any Rule** (OR Logic): Any rule can match (default)
|
|
20
|
+
- ✅ **Various Match Types**: Different matching options based on field type
|
|
21
|
+
- ✅ **Visual Feedback**: Filter icon changes when active
|
|
22
|
+
- ✅ **Single Filter Open**: Only one filter dropdown can be open at a time
|
|
23
|
+
- ✅ **ESC Key Support**: Press ESC to close the open filter
|
|
24
|
+
- ✅ **Programmatic Control**: Clear filters programmatically using `clearFilter()` method
|
|
25
|
+
- ✅ **Type-Safe**: Fully typed with TypeScript
|
|
26
|
+
- ✅ **Standalone Component**: Works with Angular 14+ standalone components
|
|
27
|
+
- ✅ **Fully Customizable**: Configurable inputs for customization
|
|
28
|
+
- ✅ **Accessible**: ARIA labels and keyboard navigation support
|
|
29
|
+
- ✅ **Data Adaptive**: Simply update `columnKey` and `columnName` when your data changes
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install ngx-column-filter-popup
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Note**: This package is published with TypeScript source files. Make sure your Angular project has TypeScript configured to compile these files.
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
### Standalone Component (Angular 14+)
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { Component } from '@angular/core';
|
|
45
|
+
import { ColumnFilterComponent } from 'ngx-column-filter-popup';
|
|
46
|
+
import { FilterConfig, applyColumnFilter } from 'ngx-column-filter-popup';
|
|
47
|
+
|
|
48
|
+
@Component({
|
|
49
|
+
selector: 'app-example',
|
|
50
|
+
imports: [ColumnFilterComponent],
|
|
51
|
+
template: `
|
|
52
|
+
<lib-column-filter
|
|
53
|
+
columnName="first name"
|
|
54
|
+
columnKey="firstName"
|
|
55
|
+
(filterApplied)="onFilterApplied($event)"
|
|
56
|
+
(filterCleared)="onFilterCleared()">
|
|
57
|
+
</lib-column-filter>
|
|
58
|
+
`
|
|
59
|
+
})
|
|
60
|
+
export class ExampleComponent {
|
|
61
|
+
onFilterApplied(filterConfig: FilterConfig) {
|
|
62
|
+
console.log('Filter applied:', filterConfig);
|
|
63
|
+
// Apply filter to your data
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
onFilterCleared() {
|
|
67
|
+
console.log('Filter cleared');
|
|
68
|
+
// Clear filter from your data
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Module-Based (Optional)
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { NgModule } from '@angular/core';
|
|
77
|
+
import { ColumnFilterModule } from 'ngx-column-filter-popup';
|
|
78
|
+
|
|
79
|
+
@NgModule({
|
|
80
|
+
imports: [ColumnFilterModule],
|
|
81
|
+
// ...
|
|
82
|
+
})
|
|
83
|
+
export class YourModule {}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Field Types
|
|
87
|
+
|
|
88
|
+
### Text Field (Default)
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<lib-column-filter
|
|
92
|
+
columnName="name"
|
|
93
|
+
columnKey="name"
|
|
94
|
+
fieldType="text"
|
|
95
|
+
(filterApplied)="onFilter($event)">
|
|
96
|
+
</lib-column-filter>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Currency Field
|
|
100
|
+
|
|
101
|
+
```html
|
|
102
|
+
<lib-column-filter
|
|
103
|
+
columnName="balance"
|
|
104
|
+
columnKey="balance"
|
|
105
|
+
fieldType="currency"
|
|
106
|
+
currencySymbol="$"
|
|
107
|
+
(filterApplied)="onBalanceFilter($event)">
|
|
108
|
+
</lib-column-filter>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Age/Number Field
|
|
112
|
+
|
|
113
|
+
```html
|
|
114
|
+
<lib-column-filter
|
|
115
|
+
columnName="age"
|
|
116
|
+
columnKey="age"
|
|
117
|
+
fieldType="age"
|
|
118
|
+
(filterApplied)="onAgeFilter($event)">
|
|
119
|
+
</lib-column-filter>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Date Field
|
|
123
|
+
|
|
124
|
+
```html
|
|
125
|
+
<lib-column-filter
|
|
126
|
+
columnName="date"
|
|
127
|
+
columnKey="date"
|
|
128
|
+
fieldType="date"
|
|
129
|
+
(filterApplied)="onDateFilter($event)">
|
|
130
|
+
</lib-column-filter>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Status Field
|
|
134
|
+
|
|
135
|
+
```html
|
|
136
|
+
<lib-column-filter
|
|
137
|
+
columnName="status"
|
|
138
|
+
columnKey="status"
|
|
139
|
+
fieldType="status"
|
|
140
|
+
[statusOptions]="['qualified', 'unqualified', 'negotiation', 'new']"
|
|
141
|
+
(filterApplied)="onStatusFilter($event)">
|
|
142
|
+
</lib-column-filter>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## API Reference
|
|
146
|
+
|
|
147
|
+
### ColumnFilterComponent
|
|
148
|
+
|
|
149
|
+
#### Inputs
|
|
150
|
+
|
|
151
|
+
| Input | Type | Default | Description |
|
|
152
|
+
|-------|------|---------|-------------|
|
|
153
|
+
| `columnName` | `string` | `''` | Display name of the column (used in placeholder) |
|
|
154
|
+
| `columnKey` | `string` | `''` | Property name to filter on |
|
|
155
|
+
| `fieldType` | `FieldType` | `'text'` | Field type: 'text', 'currency', 'age', 'date', or 'status' |
|
|
156
|
+
| `currencySymbol` | `string` | `'$'` | Currency symbol for currency field type (optional) |
|
|
157
|
+
| `statusOptions` | `string[]` | `[]` | Array of status options for status field type (required for status) |
|
|
158
|
+
| `initialFilter` | `FilterConfig?` | `undefined` | Initial filter configuration (optional) |
|
|
159
|
+
| `placeholder` | `string?` | `undefined` | Custom placeholder text. Default: "Search by {columnName}" |
|
|
160
|
+
| `availableMatchTypes` | `MatchType[]?` | `undefined` | Customize available match types (optional) |
|
|
161
|
+
|
|
162
|
+
#### Outputs
|
|
163
|
+
|
|
164
|
+
| Output | Type | Description |
|
|
165
|
+
|--------|------|-------------|
|
|
166
|
+
| `filterApplied` | `EventEmitter<FilterConfig>` | Emitted when filter is applied |
|
|
167
|
+
| `filterCleared` | `EventEmitter<void>` | Emitted when filter is cleared |
|
|
168
|
+
|
|
169
|
+
#### Public Methods
|
|
170
|
+
|
|
171
|
+
| Method | Description |
|
|
172
|
+
|--------|-------------|
|
|
173
|
+
| `clearFilter()` | Programmatically clear all filter rules and reset the filter |
|
|
174
|
+
|
|
175
|
+
### FilterConfig Interface
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
type FieldType = 'text' | 'currency' | 'age' | 'date' | 'status';
|
|
179
|
+
|
|
180
|
+
interface FilterConfig {
|
|
181
|
+
rules: FilterRule[];
|
|
182
|
+
globalMatchMode?: GlobalMatchMode; // 'match-all-rules' | 'match-any-rule'
|
|
183
|
+
fieldType?: FieldType;
|
|
184
|
+
statusOptions?: string[];
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
interface FilterRule {
|
|
188
|
+
id: string;
|
|
189
|
+
matchType: MatchType;
|
|
190
|
+
value: string;
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Utility Functions
|
|
195
|
+
|
|
196
|
+
#### applyColumnFilter
|
|
197
|
+
|
|
198
|
+
Apply filter rules to a dataset:
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import { applyColumnFilter } from 'ngx-column-filter-popup';
|
|
202
|
+
|
|
203
|
+
const filteredData = applyColumnFilter(
|
|
204
|
+
data,
|
|
205
|
+
'columnKey',
|
|
206
|
+
filterConfig
|
|
207
|
+
);
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### itemMatchesFilter
|
|
211
|
+
|
|
212
|
+
Check if a single item matches filter rules:
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import { itemMatchesFilter } from 'ngx-column-filter-popup';
|
|
216
|
+
|
|
217
|
+
const matches = itemMatchesFilter(
|
|
218
|
+
item,
|
|
219
|
+
'columnKey',
|
|
220
|
+
filterConfig
|
|
221
|
+
);
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Programmatic Control
|
|
225
|
+
|
|
226
|
+
### Clearing Filters Programmatically
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
import { Component, ViewChild } from '@angular/core';
|
|
230
|
+
import { ColumnFilterComponent } from 'ngx-column-filter-popup';
|
|
231
|
+
|
|
232
|
+
@Component({
|
|
233
|
+
template: `
|
|
234
|
+
<lib-column-filter
|
|
235
|
+
#nameFilter
|
|
236
|
+
columnName="name"
|
|
237
|
+
columnKey="name">
|
|
238
|
+
</lib-column-filter>
|
|
239
|
+
<button (click)="clearFilter()">Clear Filter</button>
|
|
240
|
+
`
|
|
241
|
+
})
|
|
242
|
+
export class ExampleComponent {
|
|
243
|
+
@ViewChild('nameFilter') filter!: ColumnFilterComponent;
|
|
244
|
+
|
|
245
|
+
clearFilter() {
|
|
246
|
+
this.filter.clearFilter(); // Programmatically clear the filter
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Complete Example
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
import { Component } from '@angular/core';
|
|
255
|
+
import { ColumnFilterComponent } from 'ngx-column-filter-popup';
|
|
256
|
+
import { FilterConfig, applyColumnFilter } from 'ngx-column-filter-popup';
|
|
257
|
+
|
|
258
|
+
interface User {
|
|
259
|
+
id: number;
|
|
260
|
+
firstName: string;
|
|
261
|
+
lastName: string;
|
|
262
|
+
email: string;
|
|
263
|
+
age: number;
|
|
264
|
+
balance: number;
|
|
265
|
+
joinDate: string;
|
|
266
|
+
status: string;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
@Component({
|
|
270
|
+
selector: 'app-user-list',
|
|
271
|
+
imports: [ColumnFilterComponent],
|
|
272
|
+
template: `
|
|
273
|
+
<table>
|
|
274
|
+
<thead>
|
|
275
|
+
<tr>
|
|
276
|
+
<th>
|
|
277
|
+
First Name
|
|
278
|
+
<lib-column-filter
|
|
279
|
+
columnName="first name"
|
|
280
|
+
columnKey="firstName"
|
|
281
|
+
(filterApplied)="onFirstNameFilter($event)"
|
|
282
|
+
(filterCleared)="onFirstNameClear()">
|
|
283
|
+
</lib-column-filter>
|
|
284
|
+
</th>
|
|
285
|
+
<th>
|
|
286
|
+
Age
|
|
287
|
+
<lib-column-filter
|
|
288
|
+
columnName="age"
|
|
289
|
+
columnKey="age"
|
|
290
|
+
fieldType="age"
|
|
291
|
+
(filterApplied)="onAgeFilter($event)">
|
|
292
|
+
</lib-column-filter>
|
|
293
|
+
</th>
|
|
294
|
+
<th>
|
|
295
|
+
Balance
|
|
296
|
+
<lib-column-filter
|
|
297
|
+
columnName="balance"
|
|
298
|
+
columnKey="balance"
|
|
299
|
+
fieldType="currency"
|
|
300
|
+
currencySymbol="$"
|
|
301
|
+
(filterApplied)="onBalanceFilter($event)">
|
|
302
|
+
</lib-column-filter>
|
|
303
|
+
</th>
|
|
304
|
+
<th>
|
|
305
|
+
Join Date
|
|
306
|
+
<lib-column-filter
|
|
307
|
+
columnName="join date"
|
|
308
|
+
columnKey="joinDate"
|
|
309
|
+
fieldType="date"
|
|
310
|
+
(filterApplied)="onDateFilter($event)">
|
|
311
|
+
</lib-column-filter>
|
|
312
|
+
</th>
|
|
313
|
+
<th>
|
|
314
|
+
Status
|
|
315
|
+
<lib-column-filter
|
|
316
|
+
columnName="status"
|
|
317
|
+
columnKey="status"
|
|
318
|
+
fieldType="status"
|
|
319
|
+
[statusOptions]="statusOptions"
|
|
320
|
+
(filterApplied)="onStatusFilter($event)">
|
|
321
|
+
</lib-column-filter>
|
|
322
|
+
</th>
|
|
323
|
+
</tr>
|
|
324
|
+
</thead>
|
|
325
|
+
<tbody>
|
|
326
|
+
<tr *ngFor="let user of filteredUsers">
|
|
327
|
+
<td>{{ user.firstName }}</td>
|
|
328
|
+
<td>{{ user.age }}</td>
|
|
329
|
+
<td>${{ user.balance }}</td>
|
|
330
|
+
<td>{{ user.joinDate }}</td>
|
|
331
|
+
<td>{{ user.status }}</td>
|
|
332
|
+
</tr>
|
|
333
|
+
</tbody>
|
|
334
|
+
</table>
|
|
335
|
+
`
|
|
336
|
+
})
|
|
337
|
+
export class UserListComponent {
|
|
338
|
+
users: User[] = [
|
|
339
|
+
{ id: 1, firstName: 'John', lastName: 'Doe', email: 'john@example.com', age: 30, balance: 50000, joinDate: '2020-01-15', status: 'active' }
|
|
340
|
+
];
|
|
341
|
+
|
|
342
|
+
filteredUsers: User[] = [...this.users];
|
|
343
|
+
statusOptions = ['active', 'inactive', 'on-leave'];
|
|
344
|
+
|
|
345
|
+
firstNameFilter: FilterConfig | null = null;
|
|
346
|
+
ageFilter: FilterConfig | null = null;
|
|
347
|
+
balanceFilter: FilterConfig | null = null;
|
|
348
|
+
dateFilter: FilterConfig | null = null;
|
|
349
|
+
statusFilter: FilterConfig | null = null;
|
|
350
|
+
|
|
351
|
+
onFirstNameFilter(filterConfig: FilterConfig) {
|
|
352
|
+
this.firstNameFilter = filterConfig;
|
|
353
|
+
this.applyAllFilters();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
onFirstNameClear() {
|
|
357
|
+
this.firstNameFilter = null;
|
|
358
|
+
this.applyAllFilters();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
onAgeFilter(filterConfig: FilterConfig) {
|
|
362
|
+
this.ageFilter = filterConfig;
|
|
363
|
+
this.applyAllFilters();
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
onBalanceFilter(filterConfig: FilterConfig) {
|
|
367
|
+
this.balanceFilter = filterConfig;
|
|
368
|
+
this.applyAllFilters();
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
onDateFilter(filterConfig: FilterConfig) {
|
|
372
|
+
this.dateFilter = filterConfig;
|
|
373
|
+
this.applyAllFilters();
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
onStatusFilter(filterConfig: FilterConfig) {
|
|
377
|
+
this.statusFilter = filterConfig;
|
|
378
|
+
this.applyAllFilters();
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
private applyAllFilters() {
|
|
382
|
+
let result = [...this.users];
|
|
383
|
+
|
|
384
|
+
if (this.firstNameFilter) {
|
|
385
|
+
result = applyColumnFilter(result, 'firstName', this.firstNameFilter);
|
|
386
|
+
}
|
|
387
|
+
if (this.ageFilter) {
|
|
388
|
+
result = applyColumnFilter(result, 'age', this.ageFilter);
|
|
389
|
+
}
|
|
390
|
+
if (this.balanceFilter) {
|
|
391
|
+
result = applyColumnFilter(result, 'balance', this.balanceFilter);
|
|
392
|
+
}
|
|
393
|
+
if (this.dateFilter) {
|
|
394
|
+
result = applyColumnFilter(result, 'joinDate', this.dateFilter);
|
|
395
|
+
}
|
|
396
|
+
if (this.statusFilter) {
|
|
397
|
+
result = applyColumnFilter(result, 'status', this.statusFilter);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
this.filteredUsers = result;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## Documentation
|
|
406
|
+
|
|
407
|
+
For comprehensive documentation including:
|
|
408
|
+
- Detailed usage examples
|
|
409
|
+
- How to adapt to different data structures
|
|
410
|
+
- Match All Rules feature explanation
|
|
411
|
+
- Complete API reference
|
|
412
|
+
- Troubleshooting guide
|
|
413
|
+
|
|
414
|
+
See [DOCUMENTATION.md](./DOCUMENTATION.md)
|
|
415
|
+
|
|
416
|
+
For programmatic control examples, see [USAGE_EXAMPLES.md](./USAGE_EXAMPLES.md)
|
|
417
|
+
|
|
418
|
+
## Styling
|
|
419
|
+
|
|
420
|
+
The component uses SCSS and includes default styles. You can customize the appearance by overriding CSS classes:
|
|
421
|
+
|
|
422
|
+
- `.column-filter-wrapper` - Main wrapper
|
|
423
|
+
- `.filter-trigger` - Filter button
|
|
424
|
+
- `.filter-dropdown` - Dropdown container
|
|
425
|
+
- `.filter-rule` - Individual filter rule
|
|
426
|
+
- `.btn-apply` - Apply button
|
|
427
|
+
- `.btn-clear` - Clear button
|
|
428
|
+
|
|
429
|
+
## Browser Support
|
|
430
|
+
|
|
431
|
+
- Chrome (latest)
|
|
432
|
+
- Firefox (latest)
|
|
433
|
+
- Safari (latest)
|
|
434
|
+
- Edge (latest)
|
|
435
|
+
|
|
436
|
+
## Requirements
|
|
437
|
+
|
|
438
|
+
- Angular 14+
|
|
439
|
+
- TypeScript 4.7+
|
|
440
|
+
|
|
441
|
+
## License
|
|
442
|
+
|
|
443
|
+
MIT
|
|
444
|
+
|
|
445
|
+
## Author
|
|
446
|
+
|
|
447
|
+
Made with ❤️ by Shivam Sharma
|
|
448
|
+
|
|
449
|
+
## Contributing
|
|
450
|
+
|
|
451
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# Column Filter Library - Usage Examples
|
|
2
|
+
|
|
3
|
+
## 1. Clear Filter as Exported Function
|
|
4
|
+
|
|
5
|
+
You can call the `clearFilter()` method programmatically from any component:
|
|
6
|
+
|
|
7
|
+
### Using ViewChild:
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { Component, ViewChild } from '@angular/core';
|
|
11
|
+
import { ColumnFilterComponent } from 'ngx-column-filter-popup';
|
|
12
|
+
|
|
13
|
+
@Component({
|
|
14
|
+
selector: 'app-example',
|
|
15
|
+
template: `
|
|
16
|
+
<table>
|
|
17
|
+
<thead>
|
|
18
|
+
<tr>
|
|
19
|
+
<th>
|
|
20
|
+
Name
|
|
21
|
+
<lib-column-filter
|
|
22
|
+
#nameFilter
|
|
23
|
+
columnName="name"
|
|
24
|
+
columnKey="name"
|
|
25
|
+
(filterApplied)="onFilter($event)">
|
|
26
|
+
</lib-column-filter>
|
|
27
|
+
</th>
|
|
28
|
+
</tr>
|
|
29
|
+
</thead>
|
|
30
|
+
</table>
|
|
31
|
+
|
|
32
|
+
<button (click)="clearNameFilter()">Clear Name Filter</button>
|
|
33
|
+
`
|
|
34
|
+
})
|
|
35
|
+
export class ExampleComponent {
|
|
36
|
+
@ViewChild('nameFilter') nameFilter!: ColumnFilterComponent;
|
|
37
|
+
|
|
38
|
+
clearNameFilter() {
|
|
39
|
+
// Programmatically clear the filter
|
|
40
|
+
this.nameFilter.clearFilter();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
onFilter(filterConfig: FilterConfig) {
|
|
44
|
+
// Handle filter applied
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Using Multiple Filters:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { Component, ViewChildren, QueryList } from '@angular/core';
|
|
53
|
+
import { ColumnFilterComponent } from 'ngx-column-filter-popup';
|
|
54
|
+
|
|
55
|
+
@Component({
|
|
56
|
+
selector: 'app-example',
|
|
57
|
+
template: `
|
|
58
|
+
<table>
|
|
59
|
+
<thead>
|
|
60
|
+
<tr>
|
|
61
|
+
<th>
|
|
62
|
+
First Name
|
|
63
|
+
<lib-column-filter
|
|
64
|
+
#firstNameFilter
|
|
65
|
+
columnName="first name"
|
|
66
|
+
columnKey="firstName">
|
|
67
|
+
</lib-column-filter>
|
|
68
|
+
</th>
|
|
69
|
+
<th>
|
|
70
|
+
Last Name
|
|
71
|
+
<lib-column-filter
|
|
72
|
+
#lastNameFilter
|
|
73
|
+
columnName="last name"
|
|
74
|
+
columnKey="lastName">
|
|
75
|
+
</lib-column-filter>
|
|
76
|
+
</th>
|
|
77
|
+
</tr>
|
|
78
|
+
</thead>
|
|
79
|
+
</table>
|
|
80
|
+
|
|
81
|
+
<button (click)="clearAllFilters()">Clear All Filters</button>
|
|
82
|
+
`
|
|
83
|
+
})
|
|
84
|
+
export class ExampleComponent {
|
|
85
|
+
@ViewChildren(ColumnFilterComponent) filters!: QueryList<ColumnFilterComponent>;
|
|
86
|
+
|
|
87
|
+
clearAllFilters() {
|
|
88
|
+
// Clear all filters programmatically
|
|
89
|
+
this.filters.forEach(filter => {
|
|
90
|
+
filter.clearFilter();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 2. Only One Column Filter Open at a Time
|
|
99
|
+
|
|
100
|
+
This feature is automatically enabled. When you open one filter, others will automatically close.
|
|
101
|
+
|
|
102
|
+
**No additional code needed!** This works automatically.
|
|
103
|
+
|
|
104
|
+
Example:
|
|
105
|
+
- First Name filter is open
|
|
106
|
+
- User opens Last Name filter
|
|
107
|
+
- First Name filter automatically closes
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 3. ESC Key Support
|
|
112
|
+
|
|
113
|
+
Pressing the ESC key will automatically close the open filter.
|
|
114
|
+
|
|
115
|
+
**No additional code needed!** This works automatically.
|
|
116
|
+
|
|
117
|
+
### How it works:
|
|
118
|
+
1. User opens filter dropdown
|
|
119
|
+
2. User presses ESC key
|
|
120
|
+
3. Filter dropdown automatically closes
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Complete Example
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import { Component, ViewChild, ViewChildren, QueryList } from '@angular/core';
|
|
128
|
+
import { ColumnFilterComponent } from 'ngx-column-filter-popup';
|
|
129
|
+
import { FilterConfig, applyColumnFilter } from 'ngx-column-filter-popup';
|
|
130
|
+
|
|
131
|
+
interface User {
|
|
132
|
+
id: number;
|
|
133
|
+
firstName: string;
|
|
134
|
+
lastName: string;
|
|
135
|
+
email: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@Component({
|
|
139
|
+
selector: 'app-user-list',
|
|
140
|
+
imports: [ColumnFilterComponent],
|
|
141
|
+
template: `
|
|
142
|
+
<div>
|
|
143
|
+
<button (click)="clearFirstNameFilter()">Clear First Name Filter</button>
|
|
144
|
+
<button (click)="clearAllFilters()">Clear All Filters</button>
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<table>
|
|
148
|
+
<thead>
|
|
149
|
+
<tr>
|
|
150
|
+
<th>
|
|
151
|
+
First Name
|
|
152
|
+
<lib-column-filter
|
|
153
|
+
#firstNameFilter
|
|
154
|
+
columnName="first name"
|
|
155
|
+
columnKey="firstName"
|
|
156
|
+
(filterApplied)="onFirstNameFilter($event)"
|
|
157
|
+
(filterCleared)="onFirstNameClear()">
|
|
158
|
+
</lib-column-filter>
|
|
159
|
+
</th>
|
|
160
|
+
<th>
|
|
161
|
+
Last Name
|
|
162
|
+
<lib-column-filter
|
|
163
|
+
#lastNameFilter
|
|
164
|
+
columnName="last name"
|
|
165
|
+
columnKey="lastName"
|
|
166
|
+
(filterApplied)="onLastNameFilter($event)">
|
|
167
|
+
</lib-column-filter>
|
|
168
|
+
</th>
|
|
169
|
+
</tr>
|
|
170
|
+
</thead>
|
|
171
|
+
<tbody>
|
|
172
|
+
<tr *ngFor="let user of filteredUsers">
|
|
173
|
+
<td>{{ user.firstName }}</td>
|
|
174
|
+
<td>{{ user.lastName }}</td>
|
|
175
|
+
</tr>
|
|
176
|
+
</tbody>
|
|
177
|
+
</table>
|
|
178
|
+
`
|
|
179
|
+
})
|
|
180
|
+
export class UserListComponent {
|
|
181
|
+
users: User[] = [
|
|
182
|
+
{ id: 1, firstName: 'John', lastName: 'Doe', email: 'john@example.com' },
|
|
183
|
+
{ id: 2, firstName: 'Jane', lastName: 'Smith', email: 'jane@example.com' }
|
|
184
|
+
];
|
|
185
|
+
|
|
186
|
+
filteredUsers: User[] = [...this.users];
|
|
187
|
+
firstNameFilter: FilterConfig | null = null;
|
|
188
|
+
lastNameFilter: FilterConfig | null = null;
|
|
189
|
+
|
|
190
|
+
// Using ViewChild for single filter
|
|
191
|
+
@ViewChild('firstNameFilter') firstNameFilterComponent!: ColumnFilterComponent;
|
|
192
|
+
|
|
193
|
+
// Using ViewChildren for multiple filters
|
|
194
|
+
@ViewChildren(ColumnFilterComponent) allFilters!: QueryList<ColumnFilterComponent>;
|
|
195
|
+
|
|
196
|
+
// Clear single filter programmatically
|
|
197
|
+
clearFirstNameFilter() {
|
|
198
|
+
this.firstNameFilterComponent.clearFilter();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Clear all filters programmatically
|
|
202
|
+
clearAllFilters() {
|
|
203
|
+
this.allFilters.forEach(filter => {
|
|
204
|
+
filter.clearFilter();
|
|
205
|
+
});
|
|
206
|
+
// Also clear filter configs
|
|
207
|
+
this.firstNameFilter = null;
|
|
208
|
+
this.lastNameFilter = null;
|
|
209
|
+
this.filteredUsers = [...this.users];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
onFirstNameFilter(filterConfig: FilterConfig) {
|
|
213
|
+
this.firstNameFilter = filterConfig;
|
|
214
|
+
this.applyFilters();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
onFirstNameClear() {
|
|
218
|
+
this.firstNameFilter = null;
|
|
219
|
+
this.applyFilters();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
onLastNameFilter(filterConfig: FilterConfig) {
|
|
223
|
+
this.lastNameFilter = filterConfig;
|
|
224
|
+
this.applyFilters();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
private applyFilters() {
|
|
228
|
+
let result = [...this.users];
|
|
229
|
+
|
|
230
|
+
if (this.firstNameFilter) {
|
|
231
|
+
result = applyColumnFilter(result, 'firstName', this.firstNameFilter);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (this.lastNameFilter) {
|
|
235
|
+
result = applyColumnFilter(result, 'lastName', this.lastNameFilter);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
this.filteredUsers = result;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Features Summary
|
|
246
|
+
|
|
247
|
+
✅ **Clear Filter Programmatically**: Call `clearFilter()` method
|
|
248
|
+
✅ **Only One Filter Open**: Automatically handled
|
|
249
|
+
✅ **ESC Key Support**: Automatically handled
|
|
250
|
+
|
|
251
|
+
**All features work automatically - no additional configuration needed!**
|