Skip to content

Commit cc56d63

Browse files
authored
feat: show selected item's icon in trigger label if applicable (#884)
* feat: show selected item's icon in trigger label if applicable
1 parent 7e0fa79 commit cc56d63

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

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

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { HttpClientTestingModule } from '@angular/common/http/testing';
22
import { fakeAsync, flush } from '@angular/core/testing';
3+
import { By } from '@angular/platform-browser';
34
import { IconLibraryTestingModule, IconType } from '@hypertrace/assets-library';
45
import { NavigationService } from '@hypertrace/common';
6+
import { IconComponent } from '@hypertrace/components';
57
import { createHostFactory, mockProvider, SpectatorHost } from '@ngneat/spectator/jest';
8+
import { MockComponent } from 'ng-mocks';
69
import { EMPTY } from 'rxjs';
710
import { SelectControlOptionPosition } from './select-control-option.component';
811
import { SelectJustify } from './select-justify';
@@ -14,6 +17,7 @@ describe('Select Component', () => {
1417
component: SelectComponent,
1518
imports: [SelectModule, HttpClientTestingModule, IconLibraryTestingModule],
1619
declareComponent: false,
20+
declarations: [MockComponent(IconComponent)],
1721
providers: [
1822
mockProvider(NavigationService, {
1923
navigation$: EMPTY,
@@ -27,7 +31,7 @@ describe('Select Component', () => {
2731
const selectionOptions = [
2832
{ label: 'first', value: 'first-value' },
2933
{ label: 'second', value: 'second-value' },
30-
{ label: 'third', value: 'third-value', selectedLabel: 'Third Value!!!' }
34+
{ label: 'third', value: 'third-value', selectedLabel: 'Third Value!!!', icon: 'test-icon', iconColor: 'red' }
3135
];
3236

3337
test('should display initial selection', fakeAsync(() => {
@@ -146,12 +150,56 @@ describe('Select Component', () => {
146150
const optionElements = spectator.queryAll('.select-option', { root: true });
147151
spectator.click(optionElements[2]);
148152

149-
expect(onChange).toHaveBeenCalledTimes(1);
150153
expect(onChange).toHaveBeenCalledWith(selectionOptions[2].value);
151154
expect(spectator.query('.trigger-content')).toHaveText(selectionOptions[2].selectedLabel!);
152155
flush();
153156
}));
154157

158+
test('should set trigger-prefix-icon correctly', fakeAsync(() => {
159+
spectator = hostFactory(
160+
`
161+
<ht-select [icon]="icon">
162+
<ht-select-option *ngFor="let option of options" [label]="option.label" [value]="option.value" [icon]="option.icon" [iconColor]="option.iconColor">
163+
</ht-select-option>
164+
</ht-select>`,
165+
{
166+
hostProps: {
167+
options: selectionOptions,
168+
icon: 'select-level-icon'
169+
}
170+
}
171+
);
172+
spectator.tick();
173+
174+
// No selection -> select component level icon and no color
175+
expect(spectator.debugElement.query(By.css('.trigger-prefix-icon')).componentInstance.icon).toBe(
176+
'select-level-icon'
177+
);
178+
// tslint:disable-next-line:no-null-keyword
179+
expect(spectator.debugElement.query(By.css('.trigger-prefix-icon')).componentInstance.color).toBe(null);
180+
181+
// Selection with no icon -> default icon and no color
182+
spectator.click('.trigger-content');
183+
let optionElements = spectator.queryAll('.select-option', { root: true });
184+
spectator.click(optionElements[1]);
185+
spectator.tick();
186+
expect(spectator.debugElement.query(By.css('.trigger-prefix-icon')).componentInstance.icon).toBe(
187+
'select-level-icon'
188+
);
189+
expect(spectator.debugElement.query(By.css('.trigger-prefix-icon')).componentInstance.color).toBe(undefined);
190+
191+
// Selection with icon and color
192+
spectator.click('.trigger-content');
193+
optionElements = spectator.queryAll('.select-option', { root: true });
194+
spectator.click(optionElements[2]);
195+
spectator.tick();
196+
197+
expect(spectator.debugElement.query(By.css('.trigger-prefix-icon')).componentInstance.icon).toBe('test-icon');
198+
expect(spectator.debugElement.query(By.css('.trigger-prefix-icon')).componentInstance.color).toBe('red');
199+
200+
flush();
201+
}));
202+
155203
test('should set correct label alignment', fakeAsync(() => {
156204
spectator = hostFactory(
157205
`

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,13 @@ import { SelectSize } from './select-size';
5555
class="trigger-content menu-with-border"
5656
[ngClass]="[this.justifyClass]"
5757
>
58-
<ht-icon *ngIf="this.icon" class="trigger-prefix-icon" [icon]="this.icon" [size]="this.iconSize">
58+
<ht-icon
59+
*ngIf="this.getPrefixIcon(selected)"
60+
class="trigger-prefix-icon"
61+
[icon]="this.getPrefixIcon(selected)"
62+
[size]="this.iconSize"
63+
[color]="selected?.iconColor"
64+
>
5965
</ht-icon>
6066
<ht-label class="trigger-label" [label]="selected?.selectedLabel || selected?.label || this.placeholder">
6167
</ht-label>
@@ -204,6 +210,10 @@ export class SelectComponent<V> implements AfterContentInit, OnChanges {
204210
}
205211
}
206212

213+
public getPrefixIcon(selectedOption: SelectOption<V> | undefined): string | undefined {
214+
return selectedOption?.icon ?? this.icon;
215+
}
216+
207217
public ngOnChanges(changes: TypedSimpleChanges<this>): void {
208218
if (this.items !== undefined && changes.selected !== undefined) {
209219
this.selected$ = this.buildObservableOfSelected();

0 commit comments

Comments
 (0)