Skip to content

Commit c452358

Browse files
feat: adding count label on multiselect component (#865)
* feat: adding count label on multiselect component * feat: adding count label on multiselect component * feat: css changes for width calculation * feat: pr suggested chages for spacing in multiple of 4 and reduceing font size * feat: increasing font wight to 600 for consistancy * fix: pr suggested changes * fix: pr suggested changes * fix: pr suggested changes * fix: pr suggested changes Co-authored-by: Alok Singh
1 parent 7cc5e77 commit c452358

File tree

3 files changed

+40
-10
lines changed

3 files changed

+40
-10
lines changed

projects/components/src/multi-select/multi-select.component.scss

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,22 @@
5454
display: flex;
5555
width: 100%;
5656
align-items: center;
57-
padding-left: 8px;
5857

5958
.trigger-label {
6059
@include body-2-medium();
6160
padding-left: 8px;
61+
width: calc(100% - 32px - 38px);
62+
flex-grow: 1;
63+
}
64+
65+
.trigger-more-items {
66+
@include semi-bold();
67+
@include font-label($gray-9);
68+
background-color: $gray-2;
69+
padding: 0 4px;
70+
border-radius: 4px;
71+
margin-left: 8px;
72+
max-width: 38px;
6273
}
6374

6475
.trigger-icon {

projects/components/src/multi-select/multi-select.component.test.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ describe('Multi Select Component', () => {
7272
expect(spectator.query('.trigger-label-container')).toExist();
7373
expect(spectator.query('.trigger-label')).toExist();
7474
expect(spectator.query('.trigger-icon')).toExist();
75+
expect(spectator.query('.trigger-more-items')).not.toExist();
76+
77+
// Selected element is 1 as set in hostProps
78+
expect(spectator.component.selectedItemsCount).toBe(1);
7579

7680
const popoverComponent = spectator.query(PopoverComponent);
7781
expect(popoverComponent?.closeOnClick).toEqual(false);
@@ -94,6 +98,8 @@ describe('Multi Select Component', () => {
9498

9599
spectator.tick();
96100
const selectedCheckboxElements = spectator.queryAll('ht-checkbox', { root: true });
101+
expect(spectator.query('.trigger-more-items')).toExist();
102+
expect(spectator.component.selectedItemsCount).toBe(2);
97103
expect(
98104
selectedCheckboxElements.filter(checkboxElement => checkboxElement.getAttribute('ng-reflect-checked') === 'true')
99105
.length
@@ -127,6 +133,8 @@ describe('Multi Select Component', () => {
127133
expect(optionElements.length).toBe(6);
128134

129135
const selectedCheckboxElements = spectator.queryAll('ht-checkbox', { root: true });
136+
expect(spectator.query('.trigger-more-items')).toExist();
137+
expect(spectator.component.selectedItemsCount).toBe(2);
130138
expect(
131139
selectedCheckboxElements.filter(checkboxElement => checkboxElement.getAttribute('ng-reflect-checked') === 'true')
132140
.length
@@ -193,7 +201,9 @@ describe('Multi Select Component', () => {
193201

194202
expect(onChange).toHaveBeenCalledTimes(1);
195203
expect(onChange).toHaveBeenCalledWith([selectionOptions[1].value, selectionOptions[2].value]);
196-
expect(spectator.query(LabelComponent)?.label).toEqual('second and 1 more');
204+
expect(spectator.query('.trigger-more-items')).toExist();
205+
expect(spectator.component.selectedItemsCount).toBe(2);
206+
expect(spectator.query(LabelComponent)?.label).toEqual('second');
197207
flush();
198208
}));
199209

@@ -260,6 +270,8 @@ describe('Multi Select Component', () => {
260270
).toBe(0);
261271
expect(onChange).toHaveBeenCalledTimes(1);
262272
expect(onChange).toHaveBeenLastCalledWith([]);
273+
expect(spectator.query('.trigger-more-items')).not.toExist();
274+
263275
expect(spectator.query(LabelComponent)?.label).toEqual('Select options');
264276

265277
const allOptionElement = spectator.query('.select-all', { root: true });
@@ -268,10 +280,13 @@ describe('Multi Select Component', () => {
268280

269281
spectator.tick();
270282
const selectedCheckboxElements = spectator.queryAll('ht-checkbox', { root: true });
283+
expect(spectator.query('.trigger-more-items')).toExist();
271284
expect(selectedCheckboxElements.length).toBe(6);
272285

273286
expect(onChange).toHaveBeenCalledWith(selectionOptions.map(option => option.value));
274-
expect(spectator.query(LabelComponent)?.label).toEqual('first and 5 more');
287+
expect(spectator.query(LabelComponent)?.label).toEqual('first');
288+
289+
expect(spectator.query('.trigger-more-items')).toHaveText('+5');
275290

276291
spectator.setHostInput({
277292
searchMode: MultiSelectSearchMode.Disabled
@@ -314,6 +329,8 @@ describe('Multi Select Component', () => {
314329
expect(onChange).toHaveBeenCalledTimes(1);
315330
expect(onChange).toHaveBeenCalledWith([selectionOptions[1].value, selectionOptions[2].value]);
316331
expect(spectator.query(LabelComponent)?.label).toEqual('Placeholder');
332+
expect(spectator.query('.trigger-more-items')).not.toExist();
333+
expect(spectator.component.selectedItemsCount).toBe(0);
317334
flush();
318335
}));
319336

projects/components/src/multi-select/multi-select.component.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ import { MultiSelectJustify } from './multi-select-justify';
5050
<ht-icon *ngIf="this.icon" [icon]="this.icon" [size]="this.iconSize"> </ht-icon>
5151
<div *ngIf="!this.isIconOnlyMode()" class="trigger-label-container">
5252
<ht-label class="trigger-label" [label]="this.triggerLabel"></ht-label>
53+
<span *ngIf="this.selectedItemsCount > 1" class="trigger-more-items"
54+
>+{{ this.selectedItemsCount - 1 }}</span
55+
>
5356
<ht-icon class="trigger-icon" icon="${IconType.ChevronDown}" size="${IconSize.Small}"></ht-icon>
5457
</div>
5558
</div>
@@ -159,6 +162,7 @@ export class MultiSelectComponent<V> implements AfterContentInit, OnChanges {
159162

160163
public popoverOpen: boolean = false;
161164
public triggerLabel?: string;
165+
public selectedItemsCount: number = 0;
162166

163167
public ngAfterContentInit(): void {
164168
this.allOptions$ = this.allOptionsList !== undefined ? queryListAndChanges$(this.allOptionsList) : EMPTY;
@@ -234,13 +238,11 @@ export class MultiSelectComponent<V> implements AfterContentInit, OnChanges {
234238
const selectedItems: SelectOptionComponent<V>[] | undefined = this.allOptionsList?.filter(item =>
235239
this.isSelectedItem(item)
236240
);
237-
if (selectedItems === undefined || selectedItems.length === 0) {
238-
this.triggerLabel = this.placeholder;
239-
} else if (selectedItems.length === 1) {
240-
this.triggerLabel = selectedItems[0].label;
241-
} else {
242-
this.triggerLabel = `${selectedItems[0].label} and ${selectedItems.length - 1} more`;
243-
}
241+
242+
this.selectedItemsCount = selectedItems?.length ?? 0;
243+
244+
// Trigger label is placeholder in case there is element selected on multiselect
245+
this.triggerLabel = this.selectedItemsCount === 0 ? this.placeholder : (selectedItems || [])[0]?.label;
244246
}
245247
}
246248

0 commit comments

Comments
 (0)