Skip to content

Commit a4c2803

Browse files
authored
feat: Combo box forms (#1327)
* fix: adding forms support to combo box * refactor: minor style change to color picker * refactor: fix lint issues
1 parent ecc635f commit a4c2803

File tree

3 files changed

+40
-8
lines changed

3 files changed

+40
-8
lines changed

projects/components/src/color-picker/color-picker.component.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
border: 2px solid $blue-4;
1818
}
1919
}
20+
21+
.add-icon {
22+
cursor: pointer;
23+
}
2024
}
2125

2226
.container {

projects/components/src/color-picker/color-picker.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
2-
import { NG_VALUE_ACCESSOR } from '@angular/forms';
2+
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
33
import { IconType } from '@hypertrace/assets-library';
44
import { Color } from '@hypertrace/common';
55
import { IconSize } from '../icon/icon-size';
@@ -37,7 +37,7 @@ import { IconSize } from '../icon/icon-size';
3737
</div>
3838
`
3939
})
40-
export class ColorPickerComponent {
40+
export class ColorPickerComponent implements ControlValueAccessor {
4141
@Input()
4242
public selected?: string;
4343

projects/components/src/combo-box/combo-box.component.ts

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ import {
1313
ViewChild,
1414
ViewChildren
1515
} from '@angular/core';
16+
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
1617
import { IconType } from '@hypertrace/assets-library';
1718
import { DomElementScrollIntoViewService, isNonEmptyString, TypedSimpleChanges } from '@hypertrace/common';
18-
import { isNil } from 'lodash-es';
19+
import { isEmpty, isNil } from 'lodash-es';
1920
import { IconSize } from '../icon/icon-size';
2021
import { PopoverRef } from '../popover/popover-ref';
2122
import { PopoverComponent } from '../popover/popover.component';
@@ -25,6 +26,13 @@ import { ComboBoxMode, ComboBoxOption, ComboBoxResult } from './combo-box-api';
2526
selector: 'ht-combo-box',
2627
styleUrls: ['./combo-box.component.scss'],
2728
changeDetection: ChangeDetectionStrategy.OnPush,
29+
providers: [
30+
{
31+
provide: NG_VALUE_ACCESSOR,
32+
multi: true,
33+
useExisting: ComboBoxComponent
34+
}
35+
],
2836
template: `
2937
<ht-popover (popoverOpen)="this.onPopoverOpen($event)" (popoverClose)="this.onPopoverClose()" class="combo-box">
3038
<ht-popover-trigger>
@@ -113,7 +121,7 @@ import { ComboBoxMode, ComboBoxOption, ComboBoxResult } from './combo-box-api';
113121
</ht-popover>
114122
`
115123
})
116-
export class ComboBoxComponent<TValue = string> implements AfterViewInit, OnChanges, OnDestroy {
124+
export class ComboBoxComponent<TValue = string> implements AfterViewInit, OnChanges, OnDestroy, ControlValueAccessor {
117125
@Input()
118126
public mode?: ComboBoxMode = ComboBoxMode.Input;
119127

@@ -176,6 +184,9 @@ export class ComboBoxComponent<TValue = string> implements AfterViewInit, OnChan
176184

177185
public createOption?: ComboBoxOption<TValue>;
178186

187+
private propagateControlValueChange?: (value: string | undefined) => void;
188+
private propagateControlValueChangeOnTouch?: (value: string | undefined) => void;
189+
179190
public constructor(
180191
private readonly changeDetectorRef: ChangeDetectorRef,
181192
private readonly scrollIntoViewService: DomElementScrollIntoViewService
@@ -204,10 +215,9 @@ export class ComboBoxComponent<TValue = string> implements AfterViewInit, OnChan
204215
}
205216

206217
private setFilteredOptions(searchText?: string): void {
207-
this.filteredOptions =
208-
searchText === undefined
209-
? this.options ?? []
210-
: (this.options ?? []).filter(option => option.text.toLowerCase().includes(searchText.toLowerCase()));
218+
this.filteredOptions = isEmpty(searchText)
219+
? this.options ?? []
220+
: (this.options ?? []).filter(option => option.text.toLowerCase().includes(searchText!.toLowerCase()));
211221
this.createOption = this.isShowCreateOption(searchText) ? this.buildCreateOption(searchText) : undefined;
212222
this.setHighlightedOptionIndex();
213223
}
@@ -227,6 +237,7 @@ export class ComboBoxComponent<TValue = string> implements AfterViewInit, OnChan
227237
this.measureText();
228238
this.setHighlightedOptionIndex();
229239
this.textChange.emit(this.text);
240+
this.propagateValueChangeToFormControl(this.text);
230241
}
231242
}
232243

@@ -405,4 +416,21 @@ export class ComboBoxComponent<TValue = string> implements AfterViewInit, OnChan
405416
this.changeDetectorRef.markForCheck(); // Yes, required
406417
});
407418
}
419+
420+
private propagateValueChangeToFormControl(value?: string): void {
421+
this.propagateControlValueChange?.(value);
422+
this.propagateControlValueChangeOnTouch?.(value);
423+
}
424+
425+
public writeValue(text?: string): void {
426+
this.text = text;
427+
}
428+
429+
public registerOnChange(onChange: (value?: string) => void): void {
430+
this.propagateControlValueChange = onChange;
431+
}
432+
433+
public registerOnTouched(onTouch: (value?: string) => void): void {
434+
this.propagateControlValueChangeOnTouch = onTouch;
435+
}
408436
}

0 commit comments

Comments
 (0)