Skip to content

Commit

Permalink
feat: (Core) add Search Field functionality to Combobox component (#4354
Browse files Browse the repository at this point in the history
)

* add search field functionality to Combobox

* add tests
  • Loading branch information
InnaAtanasova committed Jan 20, 2021
1 parent d9d95a5 commit 0eefde9
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@

<separator></separator>

<fd-docs-section-title id="combobox-standard" componentName="combobox">Combobox as Search Field</fd-docs-section-title>
<description>Set the <code>isSearch</code> property to true to use Combobox as a Search Field. The input-group addon is changed to 'search' and additional Clear button will appear when the user enters a value in the input field. The Clear button can be hidden by setting the <code>showClearButton</code> to false. By default it's set to true.</description>
<component-example>
<fd-combobox-search-field-example></fd-combobox-search-field-example>
</component-example>
<code-example [exampleFiles]="comboboxSearchFieldExample"></code-example>

<separator></separator>

<fd-docs-section-title id="combobox-customFilter" componentName="combobox"> Custom Filter </fd-docs-section-title>
<description>
The input supports custom filters through the <code>filterFn</code> input function. Simply pass a function which
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import * as comboboxSeaHtml from '!raw-loader!./examples/combobox-search-functio
import * as comboboxProgramHtml from '!raw-loader!./examples/combobox-open-control-example.component.html';
import * as comboboxProgramTs from '!raw-loader!./examples/combobox-open-control-example.component.ts';
import { ExampleFile } from '../../../documentation/core-helpers/code-example/example-file';
import * as comboboxSearchFieldHTMLSrc from '!raw-loader!./examples/combobox-search-field-example.component.html';
import * as comboboxSearchFieldTSSrc from '!raw-loader!./examples/combobox-search-field-example.component.ts';

@Component({
selector: 'fd-combobox-docs',
Expand Down Expand Up @@ -232,4 +234,18 @@ export class ComboboxDocsComponent {
fileName: 'combobox-includes-example'
}
];

comboboxSearchFieldExample: ExampleFile[] = [
{
language: 'html',
code: comboboxSearchFieldHTMLSrc,
fileName: 'combobox-search-field-example'
},
{
language: 'typescript',
component: 'ComboboxExampleComponent',
code: comboboxSearchFieldTSSrc,
fileName: 'combobox-search-field-example'
}
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<div fd-form-item>
<label fd-form-label>Search Field</label>
<fd-combobox
maxHeight="250px"
placeholder="Type some text..."
[isSearch]="true"
[dropdownValues]="fruits"
[(ngModel)]="searchTerm">
</fd-combobox>
</div>
<small>Search Term: {{ searchTerm }}</small>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Component } from '@angular/core';

@Component({
selector: 'fd-combobox-search-field-example',
templateUrl: './combobox-search-field-example.component.html'
})
export class ComboboxSearchFieldExampleComponent {
searchTerm = '';
fruits = ['Apple', 'Pineapple', 'Banana', 'Kiwi', 'Strawberry', 'Blueberry', 'Orange', 'Lemon', 'Raspberry', 'Grapefruit', 'Apricot', 'Avocado', 'Cherry'];
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ComboboxOpenControlExampleComponent } from './combobox-open-control-exa
import { ComboboxSearchFunctionExampleComponent } from './combobox-search-function-example.component';
import { ComboboxTemplateExampleComponent } from './combobox-template-example.component';
import { ComboboxIncludesExampleComponent } from './combobox-includes-example.component';
import { ComboboxSearchFieldExampleComponent } from './combobox-search-field-example.component'

export * from './combobox-mobile/combobox-mobile-example.component';
export * from './combobox-async-example.component';
Expand All @@ -26,6 +27,7 @@ export * from './combobox-height-example.component';
export * from './combobox-open-control-example.component';
export * from './combobox-search-function-example.component';
export * from './combobox-template-example.component';
export * from './combobox-search-field-example.component';

export const examples = [
ComboboxMobileExampleComponent,
Expand All @@ -41,5 +43,6 @@ export const examples = [
ComboboxOpenControlExampleComponent,
ComboboxSearchFunctionExampleComponent,
ComboboxTemplateExampleComponent,
ComboboxIncludesExampleComponent
ComboboxIncludesExampleComponent,
ComboboxSearchFieldExampleComponent
];
18 changes: 17 additions & 1 deletion libs/core/src/lib/combobox/combobox.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<ng-template #desktopTemplate>
<fd-popover
additionalBodyClass="fd-popover-custom-list"
[class.fd-combobox-full-width]="isSearch"
[isOpen]="open && displayedValues && displayedValues.length"
(isOpenChange)="isOpenChangeHandle($event)"
[fillControlMode]="fillControlMode"
Expand Down Expand Up @@ -41,7 +42,7 @@
<fd-input-group
[compact]="compact"
[button]="showDropdownButton"
[glyph]="showDropdownButton ? glyph : null"
[glyph]="showDropdownButton ? glyphValue : null"
[state]="state"
[buttonFocusable]="buttonFocusable"
[disabled]="disabled || readOnly"
Expand Down Expand Up @@ -73,6 +74,21 @@
(focus)="onTouched()"
(blur)="handleBlur()"
/>
<span
class="fd-input-group__addon fd-input-group__addon--button"
[class.fd-input-group__addon--compact]="compact"
*ngIf="isSearch && showClearButton && inputText && inputText.length > 0">
<button
fd-button
class="fd-input-group__button"
type="button"
fdType="transparent"
title="Clear input"
[class.fd-button--compact]="compact"
(click)="_handleClearSearchTerm()">
<fd-icon glyph="decline"></fd-icon>
</button>
</span>
</fd-input-group>
</ng-template>

Expand Down
4 changes: 4 additions & 0 deletions libs/core/src/lib/combobox/combobox.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@
.fd-list__item.fd-combobox-list-item {
cursor: pointer;
}

.fd-combobox-full-width {
width: 100%;
}
19 changes: 19 additions & 0 deletions libs/core/src/lib/combobox/combobox.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,4 +222,23 @@ describe('ComboboxComponent', () => {
expect(component.onChange).toHaveBeenCalled();
expect(component.inputText).toEqual('test');
});

it('should change the addon to search when combobox is used as search field', () => {
component.isSearch = true;
expect(component.glyphValue).toBe('search');
});

it('should render two buttons when combobox is used as search field and there is input text', () => {
let addOns = fixture.nativeElement.querySelectorAll('button');
expect(addOns.length).toBe(1);
component.isSearch = true;
component.communicateByObject = true;
component.displayFn = (item: any): string => {
return item.displayedValue;
};
component.inputText = 'displayedValue2';
(<any>component)._cdRef.detectChanges();
addOns = fixture.nativeElement.querySelectorAll('button');
expect(addOns.length).toBe(2);
});
});
29 changes: 29 additions & 0 deletions libs/core/src/lib/combobox/combobox.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,22 @@ export class ComboboxComponent implements ComboboxInterface, ControlValueAccesso
@Input()
placeholder: string;

/**
* Whether the Combobox is a Search Field
*/
@Input()
isSearch = false;

/** Icon to display in the right-side button. */
@Input()
glyph = 'navigation-down-arrow';

/**
* Whether to show the clear search term button when the Combobox is a Search Field
*/
@Input()
showClearButton = true;

/**
* The trigger events that will open/close the options popover.
* Accepts any [HTML DOM Events](https://www.w3schools.com/jsref/dom_obj_event.asp).
Expand Down Expand Up @@ -412,6 +424,23 @@ export class ComboboxComponent implements ComboboxInterface, ControlValueAccesso
this.onTouched();
}

/** Get the glyph value based on whether the combobox is used as a search field or not. */
get glyphValue(): string {
return this.isSearch ? 'search' : 'navigation-down-arrow';
}

/** @hidden */
_handleClearSearchTerm(): void {
this.inputTextValue = '';
this.inputTextChange.emit('');
this.displayedValues = this.dropdownValues;
if (!this.mobile) {
this._propagateChange();
}
this.onTouched();
this._cdRef.detectChanges();
}

/** @hidden */
writeValue(value: any): void {
this.inputTextValue = this.displayFn(value);
Expand Down
4 changes: 3 additions & 1 deletion libs/core/src/lib/combobox/combobox.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ComboboxComponent } from './combobox.component';
import { ButtonModule } from '../button/button.module';
import { InputGroupModule } from '../input-group/input-group.module';
import { ListModule } from '../list/list.module';
import { IconModule } from '../icon/icon.module';
import { AutoCompleteDirective } from './auto-complete.directive';

@NgModule({
Expand All @@ -21,7 +22,8 @@ import { AutoCompleteDirective } from './auto-complete.directive';
PipeModule,
ButtonModule,
InputGroupModule,
ListModule
ListModule,
IconModule
],
exports: [ComboboxComponent]
})
Expand Down

0 comments on commit 0eefde9

Please sign in to comment.