Skip to content

Commit

Permalink
Merge pull request #11462 from cetincakiroglu/issue-11461
Browse files Browse the repository at this point in the history
Fixed #11461 - TreeSelect | Filter
  • Loading branch information
yigitfindikli authored May 6, 2022
2 parents ed3b308 + f68763a commit 4a9fadf
Show file tree
Hide file tree
Showing 47 changed files with 2,011 additions and 12 deletions.
14 changes: 7 additions & 7 deletions src/app/components/tree/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -521,11 +521,11 @@ export class UITreeNode implements OnInit {
<i [class]="'p-tree-loading-icon pi-spin ' + loadingIcon"></i>
</div>
<ng-container *ngTemplateOutlet="headerTemplate"></ng-container>
<div *ngIf="filter" class="p-tree-filter-container">
<input #filter type="text" autocomplete="off" class="p-tree-filter p-inputtext p-component" [attr.placeholder]="filterPlaceholder"
(keydown.enter)="$event.preventDefault()" (input)="_filter($event.target.value)">
<span class="p-tree-filter-icon pi pi-search"></span>
</div>
<div *ngIf="filter" class="p-tree-filter-container">
<input #filter type="text" autocomplete="off" class="p-tree-filter p-inputtext p-component" [attr.placeholder]="filterPlaceholder"
(keydown.enter)="$event.preventDefault()" (input)="_filter($event.target.value)">
<span class="p-tree-filter-icon pi pi-search"></span>
</div>
<ng-container *ngIf="!virtualScroll; else virtualScrollList">
<div class="p-tree-wrapper" [style.max-height]="scrollHeight">
<ul class="p-tree-container" *ngIf="getRootNode()" role="tree" [attr.aria-label]="ariaLabel" [attr.aria-labelledby]="ariaLabelledBy">
Expand Down Expand Up @@ -640,6 +640,8 @@ export class Tree implements OnInit,AfterContentInit,OnChanges,OnDestroy,Blockab

@Input() filterPlaceholder: string;

@Input() filteredNodes: TreeNode[];

@Input() filterLocale: string;

@Input() scrollHeight: string;
Expand Down Expand Up @@ -692,8 +694,6 @@ export class Tree implements OnInit,AfterContentInit,OnChanges,OnDestroy,Blockab

public dragStopSubscription: Subscription;

public filteredNodes: TreeNode[];

constructor(public el: ElementRef, @Optional() public dragDropService: TreeDragDropService, public config: PrimeNGConfig) {}

ngOnInit() {
Expand Down
37 changes: 37 additions & 0 deletions src/app/components/treeselect/treeselect.css
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,43 @@
overflow: auto;
}

.p-treeselect-header {
display: flex;
align-items: center;
justify-content: space-between;
}

.p-treeselect-filter-container {
position: relative;
flex: 1 1 auto;
}

.p-treeselect-filter-icon {
position: absolute;
top: 50%;
margin-top: -.5rem;
}

.p-treeselect-filter-container .p-inputtext {
width: 100%;
}

.p-treeselect-close {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
overflow: hidden;
position: relative;
margin-left: auto;
}

.p-treeselect-clear-icon {
position: absolute;
top: 50%;
margin-top: -.5rem;
}

.p-fluid .p-treeselect {
display: flex;
}
68 changes: 63 additions & 5 deletions src/app/components/treeselect/treeselect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {OverlayService, PrimeNGConfig, PrimeTemplate, SharedModule, TranslationK
import {animate, style, transition, trigger, AnimationEvent} from '@angular/animations';
import {NG_VALUE_ACCESSOR} from '@angular/forms';
import {ConnectedOverlayScrollHandler, DomHandler} from 'primeng/dom';
import {TreeModule} from 'primeng/tree';
import {Tree, TreeModule} from 'primeng/tree';
import {ZIndexUtils} from 'primeng/utils'


Expand Down Expand Up @@ -44,14 +44,22 @@ export const TREESELECT_VALUE_ACCESSOR: any = {
<div class="p-treeselect-trigger">
<span class="p-treeselect-trigger-icon pi pi-chevron-down"></span>
</div>
<div #overlayRef class="p-treeselect-panel p-component" *ngIf="overlayVisible" (click)="onOverlayClick($event)"
[@overlayAnimation]="{value: 'visible', params: {showTransitionParams: showTransitionOptions, hideTransitionParams: hideTransitionOptions}}" (@overlayAnimation.start)="onOverlayAnimationStart($event)" (@overlayAnimation.done)="onOverlayAnimationDone($event)">
<ng-container *ngTemplateOutlet="headerTemplate; context: {$implicit: value, options: options}"></ng-container>
<div class="p-treeselect-header" *ngIf="filter">
<div class="p-treeselect-filter-container">
<input #filter type="text" autocomplete="off" class="p-treeselect-filter p-inputtext p-component" [attr.placeholder]="filterPlaceholder" (keydown.enter)="$event.preventDefault()" (input)="onFilterInput($event)" [value]="filterValue">
<span class="p-treeselect-filter-icon pi pi-search"></span>
</div>
<button class="p-treeselect-close p-link" (click)="hide()">
<span class="p-treeselect-filter-icon pi pi-times"></span>
</button>
</div>
<div class="p-treeselect-items-wrapper" [ngStyle]="{'max-height': scrollHeight}">
<p-tree [value]="options" [propagateSelectionDown]="propagateSelectionDown" [propagateSelectionUp]="propagateSelectionUp" [selectionMode]="selectionMode" (selectionChange)="onSelectionChange($event)" [selection]="value"
<p-tree #tree [value]="options" [propagateSelectionDown]="propagateSelectionDown" [propagateSelectionUp]="propagateSelectionUp" [selectionMode]="selectionMode" (selectionChange)="onSelectionChange($event)" [selection]="value"
[metaKeySelection]="metaKeySelection" (onNodeExpand)="nodeExpand($event)" (onNodeCollapse)="nodeCollapse($event)"
(onNodeSelect)="onSelect($event)" (onNodeUnselect)="onUnselect($event)"></p-tree>
(onNodeSelect)="onSelect($event)" (onNodeUnselect)="onUnselect($event)" [filterBy]="filterBy" [filterMode]="filterMode" [filterPlaceholder]="filterPlaceholder" [filterLocale]="filterLocale" [filterInputAutoFocus]="filterInputAutoFocus" [filteredNodes]="filteredNodes"></p-tree>
<div *ngIf="emptyOptions" class="p-treeselect-empty-message">
<ng-container *ngIf="!emptyTemplate; else empty">
{{emptyMessageText}}
Expand Down Expand Up @@ -112,10 +120,24 @@ export class TreeSelect implements AfterContentInit {

@Input() appendTo: any;

@Input() filter: boolean = false;

@Input() filterBy: string = 'label';

@Input() filterMode: string = 'lenient';

@Input() filterPlaceholder: string;

@Input() filterLocale: string;

@Input() filterInputAutoFocus: boolean = true;

@Input() propagateSelectionDown: boolean = true;

@Input() propagateSelectionUp: boolean = true;

@Input() resetFilterOnHide: boolean = true;

@Input() get options(): any[] {
return this._options;
};
Expand All @@ -134,6 +156,10 @@ export class TreeSelect implements AfterContentInit {

@ViewChild('focusInput') focusInput: ElementRef;

@ViewChild('filter') filterViewChild: ElementRef;

@ViewChild('tree') treeViewChild: Tree;

@Output() onNodeExpand: EventEmitter<any> = new EventEmitter();

@Output() onNodeCollapse: EventEmitter<any> = new EventEmitter();
Expand All @@ -142,10 +168,18 @@ export class TreeSelect implements AfterContentInit {

@Output() onHide: EventEmitter<any> = new EventEmitter();

@Output() onFilter: EventEmitter<any> = new EventEmitter();

@Output() onNodeUnselect: EventEmitter<any> = new EventEmitter();

@Output() onNodeSelect: EventEmitter<any> = new EventEmitter();

public filteredNodes: TreeNode[];

filterValue: string = null;

serializedValue: any[];

valueTemplate: TemplateRef<any>;

headerTemplate: TemplateRef<any>;
Expand Down Expand Up @@ -238,7 +272,7 @@ export class TreeSelect implements AfterContentInit {
if (this.overlayVisible){
this.hide();
}
else
else
this.show();

this.focusInput.nativeElement.focus();
Expand Down Expand Up @@ -291,15 +325,34 @@ export class TreeSelect implements AfterContentInit {
}
}

onFilterInput(event) {
this.filterValue = event.target.value;
this.treeViewChild._filter(this.filterValue);
this.onFilter.emit({
originalEvent: event,
filteredValue: this.treeViewChild.filteredNodes
});
}

show() {
this.overlayVisible = true;
}

hide() {
this.overlayVisible = false;
this.resetFilter();
this.cd.markForCheck();
}

resetFilter() {
if (this.filter && !this.resetFilterOnHide) {
this.filteredNodes = this.treeViewChild.filteredNodes;
this.treeViewChild.resetFilter();
} else {
this.filterValue = null;
}
}

onOverlayClick(event) {
this.overlayService.add({
originalEvent: event,
Expand Down Expand Up @@ -425,6 +478,11 @@ export class TreeSelect implements AfterContentInit {

onOverlayEnter() {
ZIndexUtils.set('overlay', this.overlayEl, this.config.zIndex.overlay);

if(this.filter && this.filterInputAutoFocus) {
this.filterViewChild.nativeElement.focus();
}

this.appendContainer();
this.alignOverlay();
this.bindOutsideClickListener();
Expand Down
51 changes: 51 additions & 0 deletions src/app/showcase/components/treeselect/treeselectdemo.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ <h5>Multiple</h5>

<h5>Checkbox</h5>
<p-treeSelect [(ngModel)]="selectedNodes2" [options]="nodes3" display="chip" [metaKeySelection]="false" selectionMode="checkbox" placeholder="Select Item"></p-treeSelect>

<h5>Filter</h5>
<p-treeSelect [(ngModel)]="selectedNodes3" [options]="nodes4" [filter]="true" [filterInputAutoFocus]="true" [resetFilterOnHide]="false" [metaKeySelection]="false" selectionMode="checkbox" placeholder="Select Item"></p-treeSelect>
</div>
</div>

Expand Down Expand Up @@ -350,6 +353,42 @@ <h5>Properties</h5>
<td>Defines how multiple items can be selected, when true metaKey needs to be pressed to select or unselect an item and when set to false selection of each item
can be toggled individually. On touch enabled devices, metaKeySelection is turned off automatically.</td>
</tr>
<tr>
<td>filter</td>
<td>boolean</td>
<td>false</td>
<td>When specified, displays an input field to filter the items.</td>
</tr>
<tr>
<td>filterBy</td>
<td>string</td>
<td>label</td>
<td>When filtering is enabled, filterBy decides which field or fields (comma separated) to search against.</td>
</tr>
<tr>
<td>filterMode</td>
<td>string</td>
<td>lenient</td>
<td>Mode for filtering valid values are "lenient" and "strict". Default is lenient.</td>
</tr>
<tr>
<td>filterPlaceholder</td>
<td>string</td>
<td>null</td>
<td>Placeholder text to show when filter input is empty.</td>
</tr>
<tr>
<td>filterLocale</td>
<td>string</td>
<td>undefined</td>
<td>Locale to use in filtering. The default locale is the host environment's current locale.</td>
</tr>
<tr>
<td>resetFilterOnHide</td>
<td>boolean</td>
<td>true</td>
<td>Clears the filter value when hiding the dropdown.</td>
</tr>
</tbody>
</table>
</div>
Expand All @@ -375,6 +414,12 @@ <h5>Events</h5>
<td>-</td>
<td>Callback to invoke when the overlay is hidden.</td>
</tr>
<tr>
<td>onFilter</td>
<td>event.filter: Filter value used in filtering.<br>
event.filteredValue: Filtered data after running the filtering.</td>
<td>Callback to invoke when data is filtered.</td>
</tr>
<tr>
<td>onNodeSelect</td>
<td>node: Node instance</td>
Expand Down Expand Up @@ -491,6 +536,9 @@ <h5>Dependencies</h5>

&lt;h5&gt;Checkbox&lt;/h5&gt;
&lt;p-treeSelect [(ngModel)]="selectedNodes2" [options]="nodes3" display="chip" [metaKeySelection]="false" selectionMode="checkbox" placeholder="Select Item"&gt;&lt;/p-treeSelect&gt;

&lt;h5&gt;Filter&lt;/h5&gt;
&lt;p-treeSelect [(ngModel)]="selectedNodes3" [options]="nodes4" [metaKeySelection]="false" selectionMode="checkbox" placeholder="Select Item" [filter]="true" [filterInputAutoFocus]="true"&gt;&lt;/p-treeSelect&gt;
</app-code>
<app-code lang="typescript" ngNonBindable ngPreserveWhitespaces>
export class TreeSelectModule &#123;
Expand All @@ -500,6 +548,8 @@ <h5>Dependencies</h5>

nodes3: any[];

nodes4: any[];

selectedNodes1: any[] = [];

selectedNodes2: any[] = [];
Expand All @@ -512,6 +562,7 @@ <h5>Dependencies</h5>
this.nodeService.getFiles().then(files => this.nodes1 = files);
this.nodeService.getFiles().then(files => this.nodes2 = files);
this.nodeService.getFiles().then(files => this.nodes3 = files);
this.nodeService.getFiles().then(files => this.nodes4 = files);
&#125;
&#125;
</app-code>
Expand Down
5 changes: 5 additions & 0 deletions src/app/showcase/components/treeselect/treeselectdemo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ export class TreeSelectDemo {
nodes2: any[];

nodes3: any[];

nodes4: any[];

selectedNodes1: any[] = [];

selectedNodes2: any[] = [];

selectedNodes3: any[] = [];

selectedNode: any;

constructor(public nodeService: NodeService) { }
Expand All @@ -29,5 +33,6 @@ export class TreeSelectDemo {
this.nodeService.getFiles().then(files => this.nodes1 = files);
this.nodeService.getFiles().then(files => this.nodes2 = files);
this.nodeService.getFiles().then(files => this.nodes3 = files);
this.nodeService.getFiles().then(files => this.nodes4 = files);
}
}
44 changes: 44 additions & 0 deletions src/assets/components/themes/arya-blue/theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -1705,6 +1705,50 @@ p-treeselect.ng-invalid.ng-dirty > .p-treeselect {
border-radius: 3px;
box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);
}
.p-treeselect-panel .p-treeselect-header {
padding: 0.5rem 1rem;
border-bottom: 0 none;
color: rgba(255, 255, 255, 0.87);
background: #1e1e1e;
margin: 0;
border-top-right-radius: 3px;
border-top-left-radius: 3px;
}
.p-treeselect-panel .p-treeselect-header .p-treeselect-filter-container {
margin-right: 0.5rem;
}
.p-treeselect-panel .p-treeselect-header .p-treeselect-filter-container .p-treeselect-filter {
padding-right: 1.5rem;
}
.p-treeselect-panel .p-treeselect-header .p-treeselect-filter-container .p-treeselect-filter-icon {
right: 0.5rem;
color: rgba(255, 255, 255, 0.6);
}
.p-treeselect-panel .p-treeselect-header .p-treeselect-filter-container.p-treeselect-clearable-filter .p-treeselect-filter {
padding-right: 3rem;
}
.p-treeselect-panel .p-treeselect-header .p-treeselect-filter-container.p-treeselect-clearable-filter .p-treeselect-filter-clear-icon {
right: 2rem;
}
.p-treeselect-panel .p-treeselect-header .p-treeselect-close {
width: 2rem;
height: 2rem;
color: rgba(255, 255, 255, 0.6);
border: 0 none;
background: transparent;
border-radius: 50%;
transition: background-color 0.2s, color 0.2s, box-shadow 0.2s;
}
.p-treeselect-panel .p-treeselect-header .p-treeselect-close:enabled:hover {
color: rgba(255, 255, 255, 0.87);
border-color: transparent;
background: rgba(255, 255, 255, 0.03);
}
.p-treeselect-panel .p-treeselect-header .p-treeselect-close:focus {
outline: 0 none;
outline-offset: 0;
box-shadow: 0 0 0 1px #93cbf9;
}
.p-treeselect-panel .p-treeselect-items-wrapper .p-tree {
border: 0 none;
}
Expand Down
Loading

0 comments on commit 4a9fadf

Please sign in to comment.