ngx-column-filter-popup 1.0.7 → 1.0.8

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.
Files changed (2) hide show
  1. package/README.md +135 -55
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -297,7 +297,8 @@ export class YourModule {}
297
297
  columnName="name"
298
298
  columnKey="name"
299
299
  fieldType="text"
300
- (filterApplied)="onFilter($event)">
300
+ (filterApplied)="onFilterApplied('name', $event)"
301
+ (filterCleared)="onFilterCleared('name')">
301
302
  </lib-column-filter>
302
303
  ```
303
304
 
@@ -309,7 +310,8 @@ export class YourModule {}
309
310
  columnKey="balance"
310
311
  fieldType="currency"
311
312
  currencySymbol="$"
312
- (filterApplied)="onBalanceFilter($event)">
313
+ (filterApplied)="onFilterApplied('balance', $event)"
314
+ (filterCleared)="onFilterCleared('balance')">
313
315
  </lib-column-filter>
314
316
  ```
315
317
 
@@ -320,7 +322,8 @@ export class YourModule {}
320
322
  columnName="age"
321
323
  columnKey="age"
322
324
  fieldType="age"
323
- (filterApplied)="onAgeFilter($event)">
325
+ (filterApplied)="onFilterApplied('age', $event)"
326
+ (filterCleared)="onFilterCleared('age')">
324
327
  </lib-column-filter>
325
328
  ```
326
329
 
@@ -331,7 +334,8 @@ export class YourModule {}
331
334
  columnName="date"
332
335
  columnKey="date"
333
336
  fieldType="date"
334
- (filterApplied)="onDateFilter($event)">
337
+ (filterApplied)="onFilterApplied('date', $event)"
338
+ (filterCleared)="onFilterCleared('date')">
335
339
  </lib-column-filter>
336
340
  ```
337
341
 
@@ -343,10 +347,13 @@ export class YourModule {}
343
347
  columnKey="status"
344
348
  fieldType="status"
345
349
  [statusOptions]="['qualified', 'unqualified', 'negotiation', 'new']"
346
- (filterApplied)="onStatusFilter($event)">
350
+ (filterApplied)="onFilterApplied('status', $event)"
351
+ (filterCleared)="onFilterCleared('status')">
347
352
  </lib-column-filter>
348
353
  ```
349
354
 
355
+ > 💡 **Note**: All examples use generic handlers `onFilterApplied(columnKey, $event)` and `onFilterCleared(columnKey)` - no need for separate functions per filter!
356
+
350
357
  ## API Reference
351
358
 
352
359
  ### ColumnFilterComponent
@@ -584,8 +591,11 @@ export class ExampleComponent {
584
591
 
585
592
  ## Complete Example
586
593
 
594
+ **✅ Modern Implementation using Generic Handlers (Recommended):**
595
+
587
596
  ```typescript
588
- import { Component } from '@angular/core';
597
+ import { Component, ViewChildren, QueryList } from '@angular/core';
598
+ import { CommonModule } from '@angular/common';
589
599
  import { ColumnFilterComponent } from 'ngx-column-filter-popup';
590
600
  import { FilterConfig, applyColumnFilter } from 'ngx-column-filter-popup';
591
601
 
@@ -602,8 +612,9 @@ interface User {
602
612
 
603
613
  @Component({
604
614
  selector: 'app-user-list',
605
- imports: [ColumnFilterComponent],
615
+ imports: [CommonModule, ColumnFilterComponent],
606
616
  template: `
617
+ <button (click)="clearAllFilters()">Clear All Filters</button>
607
618
  <table>
608
619
  <thead>
609
620
  <tr>
@@ -612,8 +623,29 @@ interface User {
612
623
  <lib-column-filter
613
624
  columnName="first name"
614
625
  columnKey="firstName"
615
- (filterApplied)="onFirstNameFilter($event)"
616
- (filterCleared)="onFirstNameClear()">
626
+ [allowMultipleRules]="false"
627
+ [backendMode]="isBackendMode('firstName')"
628
+ (filterApplied)="onFilterApplied('firstName', $event)"
629
+ (filterCleared)="onFilterCleared('firstName')">
630
+ </lib-column-filter>
631
+ </th>
632
+ <th>
633
+ Last Name
634
+ <lib-column-filter
635
+ columnName="last name"
636
+ columnKey="lastName"
637
+ (filterApplied)="onFilterApplied('lastName', $event)"
638
+ (filterCleared)="onFilterCleared('lastName')">
639
+ </lib-column-filter>
640
+ </th>
641
+ <th>
642
+ Email
643
+ <lib-column-filter
644
+ columnName="email"
645
+ columnKey="email"
646
+ [backendMode]="isBackendMode('email')"
647
+ (filterApplied)="onFilterApplied('email', $event)"
648
+ (filterCleared)="onFilterCleared('email')">
617
649
  </lib-column-filter>
618
650
  </th>
619
651
  <th>
@@ -622,7 +654,8 @@ interface User {
622
654
  columnName="age"
623
655
  columnKey="age"
624
656
  fieldType="age"
625
- (filterApplied)="onAgeFilter($event)">
657
+ (filterApplied)="onFilterApplied('age', $event)"
658
+ (filterCleared)="onFilterCleared('age')">
626
659
  </lib-column-filter>
627
660
  </th>
628
661
  <th>
@@ -632,7 +665,8 @@ interface User {
632
665
  columnKey="balance"
633
666
  fieldType="currency"
634
667
  currencySymbol="$"
635
- (filterApplied)="onBalanceFilter($event)">
668
+ (filterApplied)="onFilterApplied('balance', $event)"
669
+ (filterCleared)="onFilterCleared('balance')">
636
670
  </lib-column-filter>
637
671
  </th>
638
672
  <th>
@@ -641,7 +675,8 @@ interface User {
641
675
  columnName="join date"
642
676
  columnKey="joinDate"
643
677
  fieldType="date"
644
- (filterApplied)="onDateFilter($event)">
678
+ (filterApplied)="onFilterApplied('joinDate', $event)"
679
+ (filterCleared)="onFilterCleared('joinDate')">
645
680
  </lib-column-filter>
646
681
  </th>
647
682
  <th>
@@ -651,7 +686,8 @@ interface User {
651
686
  columnKey="status"
652
687
  fieldType="status"
653
688
  [statusOptions]="statusOptions"
654
- (filterApplied)="onStatusFilter($event)">
689
+ (filterApplied)="onFilterApplied('status', $event)"
690
+ (filterCleared)="onFilterCleared('status')">
655
691
  </lib-column-filter>
656
692
  </th>
657
693
  </tr>
@@ -659,6 +695,8 @@ interface User {
659
695
  <tbody>
660
696
  <tr *ngFor="let user of filteredUsers">
661
697
  <td>{{ user.firstName }}</td>
698
+ <td>{{ user.lastName }}</td>
699
+ <td>{{ user.email }}</td>
662
700
  <td>{{ user.age }}</td>
663
701
  <td>${{ user.balance }}</td>
664
702
  <td>{{ user.joinDate }}</td>
@@ -675,67 +713,109 @@ export class UserListComponent {
675
713
 
676
714
  filteredUsers: User[] = [...this.users];
677
715
  statusOptions = ['active', 'inactive', 'on-leave'];
678
-
679
- firstNameFilter: FilterConfig | null = null;
680
- ageFilter: FilterConfig | null = null;
681
- balanceFilter: FilterConfig | null = null;
682
- dateFilter: FilterConfig | null = null;
683
- statusFilter: FilterConfig | null = null;
684
-
685
- onFirstNameFilter(filterConfig: FilterConfig) {
686
- this.firstNameFilter = filterConfig;
687
- this.applyAllFilters();
688
- }
689
716
 
690
- onFirstNameClear() {
691
- this.firstNameFilter = null;
692
- this.applyAllFilters();
693
- }
717
+ // ✅ Unified filter storage - single source of truth
718
+ filters = new Map<string, FilterConfig | null>();
694
719
 
695
- onAgeFilter(filterConfig: FilterConfig) {
696
- this.ageFilter = filterConfig;
697
- this.applyAllFilters();
698
- }
720
+ // ✅ Configuration: Which columns use backend mode
721
+ readonly backendModeColumns = new Set<string>(['firstName', 'email']);
699
722
 
700
- onBalanceFilter(filterConfig: FilterConfig) {
701
- this.balanceFilter = filterConfig;
723
+ @ViewChildren(ColumnFilterComponent) filterComponents!: QueryList<ColumnFilterComponent>;
724
+
725
+ // ✅ Generic filter handler - works for ALL columns (no separate functions needed!)
726
+ onFilterApplied(columnKey: string, filterConfig: FilterConfig): void {
727
+ this.filters.set(columnKey, filterConfig);
728
+
729
+ if (this.isBackendMode(columnKey)) {
730
+ this.sendAllBackendFiltersToBackend();
731
+ }
732
+
702
733
  this.applyAllFilters();
703
734
  }
704
735
 
705
- onDateFilter(filterConfig: FilterConfig) {
706
- this.dateFilter = filterConfig;
736
+ // Generic filter clear handler - works for ALL columns
737
+ onFilterCleared(columnKey: string): void {
738
+ this.filters.set(columnKey, null);
739
+
740
+ if (this.isBackendMode(columnKey)) {
741
+ this.sendAllBackendFiltersToBackend();
742
+ }
743
+
707
744
  this.applyAllFilters();
708
745
  }
709
746
 
710
- onStatusFilter(filterConfig: FilterConfig) {
711
- this.statusFilter = filterConfig;
712
- this.applyAllFilters();
747
+ // Check if column uses backend mode
748
+ isBackendMode(columnKey: string): boolean {
749
+ return this.backendModeColumns.has(columnKey);
713
750
  }
714
751
 
715
- private applyAllFilters() {
752
+ // Apply all filters - automatically skips backend mode columns
753
+ private applyAllFilters(): void {
716
754
  let result = [...this.users];
717
755
 
718
- if (this.firstNameFilter) {
719
- result = applyColumnFilter(result, 'firstName', this.firstNameFilter);
720
- }
721
- if (this.ageFilter) {
722
- result = applyColumnFilter(result, 'age', this.ageFilter);
723
- }
724
- if (this.balanceFilter) {
725
- result = applyColumnFilter(result, 'balance', this.balanceFilter);
726
- }
727
- if (this.dateFilter) {
728
- result = applyColumnFilter(result, 'joinDate', this.dateFilter);
729
- }
730
- if (this.statusFilter) {
731
- result = applyColumnFilter(result, 'status', this.statusFilter);
732
- }
756
+ this.filters.forEach((filterConfig, columnKey) => {
757
+ // Skip backend mode columns (handled by backend)
758
+ if (filterConfig && !this.isBackendMode(columnKey)) {
759
+ result = applyColumnFilter(result, columnKey, filterConfig);
760
+ }
761
+ });
733
762
 
734
763
  this.filteredUsers = result;
735
764
  }
765
+
766
+ // ✅ Clear all filters programmatically
767
+ clearAllFilters(): void {
768
+ this.filters.clear();
769
+ this.sendAllBackendFiltersToBackend();
770
+ this.filteredUsers = [...this.users];
771
+
772
+ // Clear UI state in all filter components (icons/inputs)
773
+ if (this.filterComponents) {
774
+ this.filterComponents.forEach((filter: ColumnFilterComponent) => {
775
+ filter.clearFilter();
776
+ });
777
+ }
778
+ }
779
+
780
+ // ✅ Send all backend filters to API
781
+ private sendAllBackendFiltersToBackend(): void {
782
+ const activeFilters: Array<{
783
+ field: string;
784
+ matchType: string;
785
+ value: string;
786
+ fieldType: string;
787
+ }> = [];
788
+
789
+ this.backendModeColumns.forEach(columnKey => {
790
+ const filterConfig = this.filters.get(columnKey);
791
+ if (filterConfig && filterConfig.rules.length > 0) {
792
+ filterConfig.rules.forEach(rule => {
793
+ if (rule.value && rule.value.trim() !== '') {
794
+ activeFilters.push({
795
+ field: columnKey,
796
+ matchType: rule.matchType,
797
+ value: rule.value.trim(),
798
+ fieldType: filterConfig.fieldType || 'text'
799
+ });
800
+ }
801
+ });
802
+ }
803
+ });
804
+
805
+ const payload = { activeFilters, count: activeFilters.length };
806
+ // Send to your backend API
807
+ console.log('Backend payload:', payload);
808
+ }
736
809
  }
737
810
  ```
738
811
 
812
+ **✨ Key Benefits of This Approach:**
813
+ - ✅ **No separate functions per filter** - One `onFilterApplied()` handles all columns
814
+ - ✅ **Easy to add new filters** - Just add HTML, no new functions needed
815
+ - ✅ **Clean and maintainable** - Map-based storage, generic handlers
816
+ - ✅ **Backend mode support** - Configurable per column
817
+ - ✅ **Single source of truth** - All filters in one Map
818
+
739
819
  ## 📖 Documentation
740
820
 
741
821
  ### For Beginners:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngx-column-filter-popup",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "A powerful, reusable Angular column filter component with support for multiple field types, advanced filtering rules, and customizable match modes",
5
5
  "keywords": [
6
6
  "angular",