Skip to content

Commit 00e9d89

Browse files
authored
fix(tree-select): disable handlers for custom matcher (#DS-4304) (#1107)
1 parent 5202a8d commit 00e9d89

11 files changed

Lines changed: 527 additions & 103 deletions

File tree

packages/components-dev/tree-select/module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import { DEV_DATA_OBJECT, devBuildFileTree, DevFileFlatNode, DevFileNode } from
3131
imports: [TreeSelectExamplesModule],
3232
selector: 'dev-examples',
3333
template: `
34+
<tree-select-custom-matcher-with-input-example />
35+
<hr />
3436
<tree-select-with-multiline-matcher-example />
3537
<hr />
3638
`,

packages/components/core/select/common.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
import { CdkConnectedOverlay } from '@angular/cdk/overlay';
2-
import { AfterContentInit, Directive, EventEmitter, Inject, OnDestroy, Optional } from '@angular/core';
2+
import {
3+
AfterContentInit,
4+
booleanAttribute,
5+
Directive,
6+
EventEmitter,
7+
Inject,
8+
Input,
9+
OnDestroy,
10+
Optional
11+
} from '@angular/core';
312
import { END, ESCAPE, HOME, SPACE } from '@koobiq/cdk/keycodes';
413
import { Subscription } from 'rxjs';
514
import { KBQ_FORM_FIELD_REF, KbqFormFieldRef } from '../form-field';
@@ -15,7 +24,9 @@ export class KbqSelectTrigger {}
1524
selector: 'kbq-select-matcher, [kbq-select-matcher]',
1625
standalone: true
1726
})
18-
export class KbqSelectMatcher {}
27+
export class KbqSelectMatcher {
28+
@Input({ transform: booleanAttribute }) useDefaultHandlers: boolean = true;
29+
}
1930

2031
@Directive({
2132
selector: 'kbq-select-footer, [kbq-select-footer]',

packages/components/tree-select/examples.tree-select.ru.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,7 @@ kbq-select-trigger - позволяет переопределить блок,
99
kbq-select-matcher - позволяет заменить все содержимое kbq-select, включая placeholder, cleaner и icon
1010

1111
<!-- example(tree-select-custom-matcher) -->
12+
13+
#### Пример с полем ввода
14+
15+
<!-- example(tree-select-custom-matcher-with-input) -->

packages/components/tree-select/tree-select.component.spec.ts

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,53 @@ class SelectWithCustomTrigger {
10791079
}
10801080
}
10811081

1082+
@Component({
1083+
selector: 'select-with-custom-matcher',
1084+
template: `
1085+
<kbq-form-field>
1086+
<kbq-tree-select #select="kbqTreeSelect" placeholder="Food" [formControl]="control">
1087+
<kbq-select-matcher class="custom-matcher" [useDefaultHandlers]="useDefaultHandlers">
1088+
{{ select.triggerValue?.split('').reverse().join('') }}
1089+
</kbq-select-matcher>
1090+
<kbq-tree-selection [dataSource]="dataSource" [treeControl]="treeControl">
1091+
<kbq-tree-option *kbqTreeNodeDef="let node" kbqTreeNodePadding>
1092+
{{ treeControl.getViewValue(node) }}
1093+
</kbq-tree-option>
1094+
1095+
<kbq-tree-option *kbqTreeNodeDef="let node; when: hasChild" kbqTreeNodePadding>
1096+
<i kbq-icon="kbq-angle-S_16" kbqTreeNodeToggle></i>
1097+
{{ treeControl.getViewValue(node) }}
1098+
</kbq-tree-option>
1099+
</kbq-tree-selection>
1100+
</kbq-tree-select>
1101+
</kbq-form-field>
1102+
`
1103+
})
1104+
class SelectWithCustomMatcher {
1105+
@ViewChild('select') select: KbqTreeSelect;
1106+
1107+
useDefaultHandlers: boolean = true;
1108+
1109+
control = new UntypedFormControl();
1110+
1111+
treeControl = new FlatTreeControl<FileFlatNode>(getLevel, isExpandable, getValue, getValue);
1112+
treeFlattener = new KbqTreeFlattener(transformer, getLevel, isExpandable, getChildren);
1113+
1114+
dataSource: KbqTreeFlatDataSource<FileNode, FileFlatNode>;
1115+
1116+
constructor() {
1117+
this.dataSource = new KbqTreeFlatDataSource(this.treeControl, this.treeFlattener);
1118+
1119+
// Build the tree nodes from Json object. The result is a list of `FileNode` with nested
1120+
// file node as children.
1121+
this.dataSource.data = buildFileTree(TREE_DATA, 0);
1122+
}
1123+
1124+
hasChild(_: number, nodeData: FileFlatNode) {
1125+
return nodeData.expandable;
1126+
}
1127+
}
1128+
10821129
@Component({
10831130
selector: 'ng-model-compare-with',
10841131
template: `
@@ -3549,6 +3596,83 @@ describe(KbqTreeSelect.name, () => {
35493596
}));
35503597
});
35513598

3599+
describe('with custom matcher', () => {
3600+
beforeEach(() => {
3601+
configureKbqTreeSelectTestingModule([SelectWithCustomMatcher]);
3602+
});
3603+
3604+
it('should allow the user to customize matcher', fakeAsync(() => {
3605+
const fixture = TestBed.createComponent(SelectWithCustomMatcher);
3606+
3607+
fixture.detectChanges();
3608+
3609+
fixture.componentInstance.control.setValue('Downloads');
3610+
fixture.detectChanges();
3611+
tick(1);
3612+
flush();
3613+
3614+
const label = fixture.debugElement.query(By.css('.custom-matcher')).nativeElement;
3615+
3616+
expect(label.textContent).toContain('sdaolnwoD');
3617+
}));
3618+
3619+
it('should allow to disable handlers for click with custom matcher', fakeAsync(() => {
3620+
const fixture = TestBed.createComponent(SelectWithCustomMatcher);
3621+
3622+
fixture.autoDetectChanges();
3623+
3624+
const trigger = fixture.debugElement.query(By.css('.kbq-select__trigger')).nativeElement;
3625+
const toggleSpyFn = jest.spyOn(fixture.componentInstance.select, 'toggle');
3626+
3627+
expect(toggleSpyFn).toHaveBeenCalledTimes(0);
3628+
3629+
trigger.click();
3630+
fixture.detectChanges();
3631+
flush();
3632+
3633+
expect(toggleSpyFn).toHaveBeenCalledTimes(1);
3634+
3635+
fixture.componentInstance.useDefaultHandlers = false;
3636+
3637+
trigger.click();
3638+
fixture.detectChanges();
3639+
flush();
3640+
3641+
expect(toggleSpyFn).toHaveBeenCalledTimes(1);
3642+
}));
3643+
3644+
it('should allow to disable handlers for keydown with custom matcher', fakeAsync(() => {
3645+
const fixture = TestBed.createComponent(SelectWithCustomMatcher);
3646+
3647+
fixture.autoDetectChanges();
3648+
3649+
const trigger = fixture.debugElement.query(By.css('.kbq-select__trigger')).nativeElement;
3650+
3651+
const triggerKeydownHandlerSpyFn = jest.spyOn(fixture.componentInstance.select, 'triggerKeydownHandler');
3652+
const panelKeydownHandlerSpyFn = jest.spyOn(fixture.componentInstance.select, 'panelKeydownHandler');
3653+
3654+
expect(triggerKeydownHandlerSpyFn).toHaveBeenCalledTimes(0);
3655+
expect(panelKeydownHandlerSpyFn).toHaveBeenCalledTimes(0);
3656+
3657+
dispatchKeyboardEvent(trigger, 'keydown', DOWN_ARROW);
3658+
fixture.detectChanges();
3659+
flush();
3660+
3661+
expect(triggerKeydownHandlerSpyFn).toHaveBeenCalledTimes(1);
3662+
expect(panelKeydownHandlerSpyFn).toHaveBeenCalledTimes(0);
3663+
3664+
fixture.componentInstance.useDefaultHandlers = false;
3665+
fixture.detectChanges();
3666+
3667+
dispatchKeyboardEvent(trigger, 'keydown', DOWN_ARROW);
3668+
fixture.detectChanges();
3669+
flush();
3670+
3671+
expect(triggerKeydownHandlerSpyFn).toHaveBeenCalledTimes(1);
3672+
expect(panelKeydownHandlerSpyFn).toHaveBeenCalledTimes(0);
3673+
}));
3674+
});
3675+
35523676
describe('when resetting the value by setting null or undefined', () => {
35533677
beforeEach(() => {
35543678
configureKbqTreeSelectTestingModule([ResetValuesSelect]);

0 commit comments

Comments
 (0)