Skip to content

Commit cea9d92

Browse files
authored
fix: support disabling select options (#968)
* fix: support disabling select options
1 parent 94a0439 commit cea9d92

File tree

6 files changed

+69
-4
lines changed

6 files changed

+69
-4
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ export class SelectOptionComponent<V> implements OnChanges, SelectOption<V> {
2727
@Input()
2828
public iconColor?: string;
2929

30+
@Input()
31+
public disabled?: boolean;
32+
3033
private readonly optionChangeSubject$: Subject<V> = new Subject<V>();
3134
public readonly optionChange$: Observable<V> = this.optionChangeSubject$.asObservable();
3235

projects/components/src/select/select-option.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export interface SelectOption<V> {
44
selectedLabel?: string;
55
icon?: string;
66
iconColor?: string;
7+
disabled?: boolean;
78
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@
165165
justify-content: space-between;
166166
white-space: nowrap;
167167

168+
&.disabled {
169+
color: $gray-5;
170+
cursor: not-allowed;
171+
}
172+
168173
.select-option-info {
169174
display: flex;
170175
flex-direction: row;

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

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { HttpClientTestingModule } from '@angular/common/http/testing';
22
import { fakeAsync, flush } from '@angular/core/testing';
33
import { By } from '@angular/platform-browser';
44
import { IconLibraryTestingModule, IconType } from '@hypertrace/assets-library';
5-
import { NavigationService } from '@hypertrace/common';
5+
import { MemoizeModule, NavigationService } from '@hypertrace/common';
66
import { IconComponent } from '@hypertrace/components';
77
import { createHostFactory, mockProvider, SpectatorHost } from '@ngneat/spectator/jest';
88
import { MockComponent } from 'ng-mocks';
@@ -15,7 +15,7 @@ import { SelectModule } from './select.module';
1515
describe('Select Component', () => {
1616
const hostFactory = createHostFactory<SelectComponent<string>>({
1717
component: SelectComponent,
18-
imports: [SelectModule, HttpClientTestingModule, IconLibraryTestingModule],
18+
imports: [SelectModule, HttpClientTestingModule, IconLibraryTestingModule, MemoizeModule],
1919
declareComponent: false,
2020
declarations: [MockComponent(IconComponent)],
2121
providers: [
@@ -282,4 +282,44 @@ describe('Select Component', () => {
282282
expect(onChange).toHaveBeenCalledWith('none-id');
283283
flush();
284284
}));
285+
286+
test('should disable select options as expected', fakeAsync(() => {
287+
const onChange = jest.fn();
288+
289+
spectator = hostFactory(
290+
`
291+
<ht-select (selectedChange)="onChange($event)">
292+
<ht-select-option *ngFor="let option of options" [label]="option.label" [value]="option.value" [disabled]="option.disabled"></ht-select-option>
293+
</ht-select>`,
294+
{
295+
hostProps: {
296+
options: [
297+
{ label: 'first', value: 'first-value' },
298+
{ label: 'second', value: 'second-value', disabled: true },
299+
{
300+
label: 'third',
301+
value: 'third-value',
302+
selectedLabel: 'Third Value!!!',
303+
icon: 'test-icon',
304+
iconColor: 'red'
305+
}
306+
],
307+
onChange: onChange
308+
}
309+
}
310+
);
311+
312+
spectator.tick();
313+
spectator.click('.trigger-content');
314+
315+
const optionElements = spectator.queryAll('.select-option', { root: true });
316+
expect(optionElements.length).toBe(3);
317+
expect(optionElements[0]).not.toHaveClass('disabled');
318+
expect(optionElements[1]).toHaveClass('disabled');
319+
expect(optionElements[2]).not.toHaveClass('disabled');
320+
spectator.click(optionElements[1]);
321+
322+
expect(onChange).not.toHaveBeenCalled();
323+
flush();
324+
}));
285325
});

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ import { SelectSize } from './select-size';
114114
*ngFor="let item of items"
115115
(click)="this.onSelectionChange(item)"
116116
class="select-option"
117-
[ngClass]="this.size"
117+
[ngClass]="this.getStyleClassesForSelectItem | htMemoize: this.size:item"
118118
>
119119
<div class="select-option-info">
120120
<ht-icon
@@ -241,6 +241,10 @@ export class SelectComponent<V> implements AfterContentInit, OnChanges {
241241
}
242242

243243
public onSelectionChange(item: SelectOptionComponent<V>): void {
244+
if (item.disabled) {
245+
return;
246+
}
247+
244248
this.selected = item.value;
245249
this.selected$ = this.buildObservableOfSelected();
246250
this.selectedChange.emit(this.selected);
@@ -255,6 +259,16 @@ export class SelectComponent<V> implements AfterContentInit, OnChanges {
255259

256260
return this.items.find(item => item.value === value);
257261
}
262+
263+
public getStyleClassesForSelectItem(size: SelectSize, item: SelectOptionComponent<V>): string[] {
264+
const styles: string[] = [size];
265+
266+
if (item.disabled) {
267+
styles.push('disabled');
268+
}
269+
270+
return styles;
271+
}
258272
}
259273

260274
export const enum SelectTriggerDisplayMode {

projects/components/src/select/select.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { CommonModule } from '@angular/common';
22
import { NgModule } from '@angular/core';
33
import { FormsModule } from '@angular/forms';
4+
import { MemoizeModule } from '@hypertrace/common';
45
import { DividerModule } from '../divider/divider.module';
56
import { IconModule } from '../icon/icon.module';
67
import { LabelModule } from '../label/label.module';
@@ -21,7 +22,8 @@ import { SelectComponent } from './select.component';
2122
LetAsyncModule,
2223
PopoverModule,
2324
TooltipModule,
24-
DividerModule
25+
DividerModule,
26+
MemoizeModule
2527
],
2628
declarations: [SelectComponent, SelectOptionComponent, SelectGroupComponent, SelectControlOptionComponent],
2729
exports: [SelectComponent, SelectOptionComponent, SelectGroupComponent, SelectControlOptionComponent]

0 commit comments

Comments
 (0)