Skip to content

Commit

Permalink
Fix select all filtered list (#914)
Browse files Browse the repository at this point in the history
* bug fixes for select all filtered list

* single item, add remove handled

* handling controls initial value incase of typeahead provided

* changes in handling controls initial value

* small condition fix

* test cases updated and condition change in init control value

* formatting changes

* formatting changes

* edge case handled while removing selected item

* formatting changes

* adding count to select all

* adding count to select all

* linting errors fixed

* typo fixed

* refactored code for better understanding

* refactoring

* lint fix

* indentation changes, private methods and variables grouped, minor ux changes

* renaming methods

* karma config thresold changes

---------

Co-authored-by: Vishal Shah <[email protected]>
  • Loading branch information
Jay Kravetz and vishal-tangoe authored Jun 7, 2023
1 parent 50bb3a2 commit 2b62a50
Show file tree
Hide file tree
Showing 4 changed files with 267 additions and 16 deletions.
2 changes: 1 addition & 1 deletion projects/go-lib/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module.exports = function (config) {
thresholds: {
statements: 93,
lines: 92,
branches: 79,
branches: 75,
functions: 88,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
{{ label }}
<go-required-text [control]="control"></go-required-text>
</label>

<ng-select
[appendTo]="appendTo"
[clearable]="clearable"
(add)="handleItemAdd($event)"
(remove)="handleItemRemove($event)"
[clearSearchOnAdd]="clearSearchOnAdd"
[closeOnSelect]="closeOnSelect"
[bindLabel]="bindLabel"
Expand All @@ -19,6 +20,7 @@
[items]="items"
[labelForId]="_id"
[loading]="loading"
(search)="handleInput($event)"
[multiple]="multiple"
[ngClass]="{
'go-select--dark': theme === 'dark',
Expand All @@ -31,27 +33,33 @@
[typeToSearchText]="typeToSearchText"
[virtualScroll]="virtualScroll"
(scrollToEnd)="onScrollToEnd()"
(scroll)="onScroll($event)">
(close)="onClose()"
(scroll)="onScroll($event)"
#select
>
<ng-template
*ngIf="multiple && items?.length"
ng-header-tmp>
ng-header-tmp
>
<button
type="button"
(click)="onSelectAll()"
class="go-select__select-all-button"
[ngClass]="{ 'go-select__select-all-button--dark' : theme === 'dark' }"
*ngIf="showSelectAll && control.value?.length < items?.length">
Select All
*ngIf="showSelectAll && (control.value?.length < items?.length || typeahead)"
>
Select {{!select.searchTerm || typeahead ? items.length : refinedItems.length}} Result(s)
</button>
<button
type="button"
(click)="onRemoveAll()"
class="go-select__select-all-button"
[ngClass]="{ 'go-select__select-all-button--dark' : theme === 'dark' }"
*ngIf="control.value">
*ngIf="control.value?.length">
Remove All
</button>
</ng-template>

<ng-container *ngIf="goSelectSelectedOption">
<ng-template ng-label-tmp let-item="item">
<ng-container *ngTemplateOutlet="goSelectSelectedOption; context: { $implicit: item }"></ng-container>
Expand All @@ -78,4 +86,4 @@
[theme]="theme">
</go-hint>

<go-form-errors [control]="control" [theme]="theme"></go-form-errors>
<go-form-errors [control]="control" [theme]="theme"></go-form-errors>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { GoFormErrorsModule } from '../go-form-errors/go-form-errors.module';
import { GoHintModule } from '../go-hint/go-hint.module';
import { GoRequiredTextModule } from '../go-required-text/go-required-text.module';
import { GoSelectComponent } from './go-select.component';
import { Subject } from 'rxjs';

describe('GoSelectComponent', () => {
let component: GoSelectComponent;
Expand All @@ -25,8 +26,7 @@ describe('GoSelectComponent', () => {
FormsModule,
ReactiveFormsModule
]
})
.compileComponents();
}).compileComponents();
}));

beforeEach(() => {
Expand All @@ -41,6 +41,11 @@ describe('GoSelectComponent', () => {
});

describe('onSelectAll()', () => {

beforeEach(() => {
component.multiple = true;
});

it('adds all of the available items to the form control value', () => {
component.bindValue = undefined;
component.items = [
Expand All @@ -66,22 +71,119 @@ describe('GoSelectComponent', () => {

expect(component.control.value).toEqual([1, 2, 3]);
});

it('should select only filtered list, when filtered and selectAll', () => {
component.bindValue = 'id';
component.items = [
{ id: 1, label: 'banana' },
{ id: 2, label: 'apple' },
{ id: 3, label: 'green apple' }
];
const filteredItems: any[] = [
{ id: 2, label: 'apple' },
{ id: 3, label: 'green apple' }
];
component.ngSelect.searchTerm = 'apple';
component.handleInput({ items: filteredItems, term: 'apple' });
component.onSelectAll();
expect(component.control.value).toEqual([2, 3]);
});

it('should select filtered list with existing items in control value, when filtered and selectAll', () => {
component.bindValue = 'id';
component.control.patchValue([4]);
component.items = [
{ id: 1, label: 'banana' },
{ id: 2, label: 'apple' },
{ id: 3, label: 'green apple' },
{ id: 4, label: 'grapes' }
];
const filteredItems: any[] = [
{ id: 2, label: 'apple' },
{ id: 3, label: 'green apple' }
];
component.ngSelect.searchTerm = 'apple';
component.handleInput({ items: filteredItems, term: 'apple' });
component.onSelectAll();
expect(component.control.value.length).toEqual(3);
});
});

describe('onSelectAll() with typeahead', () => {
beforeEach(() => {
component.typeahead = new Subject();
component.multiple = true;
});

it('should store items in previousSelectedItems', () => {
const initialItems: any[] = [
{ id: 1, label: 'banana' },
{ id: 2, label: 'apple' },
];
component.items = initialItems;
component['handleTypeAheadSelectAll']();
expect(component['previousSelectedItems']).toEqual(initialItems);
});

it('should add items in previousSelectedItems', () => {
component.handleItemAdd({ id: 1, label: 'banana' });
expect(component['previousSelectedItems']).toEqual([
{ id: 1, label: 'banana' },
]);
});

it('should remove items from previousSelectedItems', () => {
component['previousSelectedItems'] = [{ id: 1, label: 'banana' }];
component.handleItemRemove({ value: { id: 1, label: 'banana' } });
expect(component['previousSelectedItems']).toEqual([]);
});

it('handleControlInitialValue(), should assign previousSelectedItems', () => {
component.control.patchValue([1]);
component.bindValue = 'id';
component.items = [
{ id: 1, label: 'banana' },
{ id: 2, label: 'apple' },
];
component['handleControlInitialValue']();
expect(component['previousSelectedItems']).toEqual([
{ id: 1, label: 'banana' },
]);
});
});

describe('processSelectAll', () => {
it('process select all and patch value in form', () => {
component.bindValue = 'id';
const items: any[] = [
{ id: 1, label: 'banana' },
{ id: 2, label: 'apple' },
{ id: 3, label: 'green apple' },
{ id: 4, label: 'grapes' },
];

component['processSelectAll'](items);

expect(component.control.value).toEqual([1, 2, 3, 4]);
});
});

describe('onRemoveAll', () => {
it('uses removed the selected values', () => {
component.bindValue = 'id';
spyOn<any>(component, 'resetTypeAheadItems');
component.items = [
{ id: 1, label: 'Label 1' },
{ id: 2, label: 'Label 2' },
{ id: 3, label: 'Label 3' }
{ id: 3, label: 'Label 3' },
];

component.onSelectAll();

component.onRemoveAll();

expect(component.control.value).toBeNull();
expect(component['resetTypeAheadItems']).toHaveBeenCalled();
});
});
});
Loading

0 comments on commit 2b62a50

Please sign in to comment.