Skip to content

Commit

Permalink
feat: clear on add functionality, expose updateDropdownPosition (#497)
Browse files Browse the repository at this point in the history
closes #276
  • Loading branch information
rubilnikas authored and anjmao committed Apr 25, 2018
1 parent 23e56b1 commit 47f02c8
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 31 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ map: {
| placeholder | `string` | `-` | no | Placeholder text. |
| [searchable] | `boolean` | `true` | no | Allow to search for value. Default `true`|
| [searchFn] | `(term: string, item: any) => boolean` | `null` | no | Allow to filter by custom search function |
| [clearSearchOnAdd] | `boolean` | `true` | no | Clears search input when item is selected. Default `true`|
| [selectOnTab] | `boolean` | `false` | no | Select marked dropdown item using tab. Default `false`|
| [typeahead] | `Subject` | `-` | no | Custom autocomplete or advanced filter. |
| typeToSearchText | `string` | `Type to search` | no | Set custom text when using Typeahead |
Expand Down
58 changes: 29 additions & 29 deletions src/ng-select/ng-dropdown-panel.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export class NgDropdownPanelComponent implements OnInit, OnChanges, OnDestroy, A

ngAfterContentInit() {
this._whenContentReady().then(() => {
this._handleDropdownPosition();
this.updateDropdownPosition();
});
}

Expand Down Expand Up @@ -159,6 +159,34 @@ export class NgDropdownPanelComponent implements OnInit, OnChanges, OnDestroy, A
el.scrollTop = d.childHeight * (d.itemsLength + 1);
}

updateDropdownPosition() {
if (this.appendTo) {
this._appendDropdown();
this._handleDocumentResize();
}

const dropdownEl: HTMLElement = this._elementRef.nativeElement;
this._currentPosition = this._calculateCurrentPosition(dropdownEl);
const selectEl: HTMLElement = this._selectElement;
if (this._currentPosition === 'top') {
this._renderer.addClass(dropdownEl, TOP_CSS_CLASS)
this._renderer.removeClass(dropdownEl, BOTTOM_CSS_CLASS)
this._renderer.addClass(selectEl, TOP_CSS_CLASS)
this._renderer.removeClass(selectEl, BOTTOM_CSS_CLASS)
} else {
this._renderer.addClass(dropdownEl, BOTTOM_CSS_CLASS)
this._renderer.removeClass(dropdownEl, TOP_CSS_CLASS)
this._renderer.addClass(selectEl, BOTTOM_CSS_CLASS)
this._renderer.removeClass(selectEl, TOP_CSS_CLASS)
}

if (this.appendTo) {
this._updateAppendedDropdownPosition();
}

dropdownEl.style.opacity = '1';
}

private _handleOutsideClick($event: any) {
if (this._selectElement.contains($event.target)) {
return;
Expand Down Expand Up @@ -277,34 +305,6 @@ export class NgDropdownPanelComponent implements OnInit, OnChanges, OnDestroy, A
this.scrollInto(this._itemsList.markedItem)
}

private _handleDropdownPosition() {
if (this.appendTo) {
this._appendDropdown();
this._handleDocumentResize();
}

const dropdownEl: HTMLElement = this._elementRef.nativeElement;
this._currentPosition = this._calculateCurrentPosition(dropdownEl);
const selectEl: HTMLElement = this._selectElement;
if (this._currentPosition === 'top') {
this._renderer.addClass(dropdownEl, TOP_CSS_CLASS)
this._renderer.removeClass(dropdownEl, BOTTOM_CSS_CLASS)
this._renderer.addClass(selectEl, TOP_CSS_CLASS)
this._renderer.removeClass(selectEl, BOTTOM_CSS_CLASS)
} else {
this._renderer.addClass(dropdownEl, BOTTOM_CSS_CLASS)
this._renderer.removeClass(dropdownEl, TOP_CSS_CLASS)
this._renderer.addClass(selectEl, BOTTOM_CSS_CLASS)
this._renderer.removeClass(selectEl, TOP_CSS_CLASS)
}

if (this.appendTo) {
this._updateAppendedDropdownPosition();
}

dropdownEl.style.opacity = '1';
}

private _calculateCurrentPosition(dropdownEl: HTMLElement) {
if (this.position !== 'auto') {
return this.position;
Expand Down
54 changes: 53 additions & 1 deletion src/ng-select/ng-select.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1143,7 +1143,7 @@ describe('NgSelectComponent', function () {
triggerKeyDownEvent(getNgSelectElement(fixture), KeyCode.Space);
expect(fixture.componentInstance.select.isOpen).toBeTruthy();
document.getElementById('outside').click();
let event = new MouseEvent('mousedown', {bubbles: true});
let event = new MouseEvent('mousedown', { bubbles: true });
document.getElementById('outside').dispatchEvent(event);
tickAndDetectChanges(fixture);
expect(fixture.componentInstance.select.isOpen).toBeFalsy();
Expand Down Expand Up @@ -2007,6 +2007,58 @@ describe('NgSelectComponent', function () {
expect(fixture.componentInstance.select.isOpen).toBeTruthy();
}));
});

describe('clear on add', () => {
it('should clear search term by default', fakeAsync(() => {
const fixture = createTestingModule(
NgSelectTestCmp,
`<ng-select [items]="cities"
[typeahead]="filter"
bindLabel="name"
[hideSelected]="hideSelected"
[closeOnSelect]="false"
[(ngModel)]="selectedCity">
</ng-select>`);

expect(fixture.componentInstance.select.clearSearchOnAdd).toBeTruthy();

fixture.componentInstance.filter.subscribe();
fixture.componentInstance.select.filter('new');
fixture.componentInstance.cities = [{ id: 4, name: 'New York' }];
tickAndDetectChanges(fixture);
expect(fixture.componentInstance.select.itemsList.filteredItems.length).toBe(1);
expect(fixture.componentInstance.select.filterValue).toBe('new');

fixture.componentInstance.select.select(fixture.componentInstance.select.viewPortItems[0]);
expect(fixture.componentInstance.select.filterValue).toBeNull();
}));

it('should not clear search term when clearSearchOnAdd is false', fakeAsync(() => {
const fixture = createTestingModule(
NgSelectTestCmp,
`<ng-select [items]="cities"
[typeahead]="filter"
bindLabel="name"
[hideSelected]="hideSelected"
[clearSearchOnAdd]="false"
[closeOnSelect]="false"
[(ngModel)]="selectedCity">
</ng-select>`);

expect(fixture.componentInstance.select.clearSearchOnAdd).toBeFalsy();
expect(fixture.componentInstance.select.closeOnSelect).toBeFalsy();

fixture.componentInstance.filter.subscribe();
fixture.componentInstance.select.filter('new');
fixture.componentInstance.cities = [{ id: 4, name: 'New York' }, { id: 5, name: 'California' }];
tickAndDetectChanges(fixture);
expect(fixture.componentInstance.select.itemsList.filteredItems.length).toBe(2);
expect(fixture.componentInstance.select.filterValue).toBe('new');

fixture.componentInstance.select.select(fixture.componentInstance.select.viewPortItems[0]);
expect(fixture.componentInstance.select.filterValue).toBe('new');
}));
});
});

describe('Accessability', () => {
Expand Down
13 changes: 12 additions & 1 deletion src/ng-select/ng-select.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export class NgSelectComponent implements OnDestroy, OnChanges, AfterViewInit, C
@Input() virtualScroll = false;
@Input() selectableGroup = false;
@Input() searchFn = null;
@Input() clearSearchOnAdd = true;
@Input() @HostBinding('class.ng-select-typeahead') typeahead: Subject<string>;
@Input() @HostBinding('class.ng-select-multiple') multiple = false;
@Input() @HostBinding('class.ng-select-taggable') addTag: boolean | AddTagFn = false;
Expand Down Expand Up @@ -352,7 +353,11 @@ export class NgSelectComponent implements OnDestroy, OnChanges, AfterViewInit, C

select(item: NgOption) {
this.itemsList.select(item);
this._clearSearch();

if (this.clearSearchOnAdd) {
this._clearSearch();
}

this.addEvent.emit(item.value);
if (this.closeOnSelect || this.itemsList.noItemsToSelect) {
this.close();
Expand Down Expand Up @@ -455,6 +460,12 @@ export class NgSelectComponent implements OnDestroy, OnChanges, AfterViewInit, C
}
}

updateDropdownPosition() {
if (this.dropdownPanel) {
this.dropdownPanel.updateDropdownPosition();
}
}

private _setItems(items: any[]) {
const firstItem = items[0];
this.bindLabel = this.bindLabel || this._defaultLabel;
Expand Down

0 comments on commit 47f02c8

Please sign in to comment.