Description
I have a dropdown-like component that loads data from my back end. I need to have different view types for my component which I am able to achieve (i.e. Single-select dropdown, Multi-select dropdown, Radio, Checkbox).
Single-select dropdown and Radio would mean the user can select 1 value and of course Multi-select and Checkbox meaning user can select multiple values.
when I select Multi-select in View Type dropdown and try to select the default value I get this.
I will paste the entire LOV component.
`
export class CustomLovComponent
implements FormioCustomComponent<string[]>, OnInit, OnChanges, OnDestroy
{
@input() value: any = '';
@input() disabled!: boolean;
@input() lovType!: string;
@input() viewType!: string;
@output() valueChange = new EventEmitter();
@output() formioEvent = new EventEmitter();
private destroy$ = new Subject();
loading = false;
baseURL: string = this.configProvider.appSettings.coreApiUrl;
lovOptionsResponse: Options[] = [];
lovOptions: Options[] = [];
showUI = true;
constructor(
private readonly configProvider: ConfigurationProvider,
private readonly http: HttpClient,
private readonly lovOptionService: LovOptionsService,
public cdr: ChangeDetectorRef
) {}
ngOnInit() {
this.getAllLovs();
}
ngOnChanges(changes: SimpleChanges): void {
this.showUI = false;
this.lovType = changes['lovType']?.currentValue;
if (this.viewType == 'dropdownMultiSelect' || this.viewType == 'checkbox') {
this.value = typeof this.value == 'string' ? [] : this.value;
}
console.log('Insomniac: value', typeof this.value, this.value);
this.showUI = true;
this.getLOVOptions();
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
private getLOVOptions(): void {
if (!this.isObjectEmpty(this.lovType)) {
this.loading = true;
this.cdr.detectChanges();
this.lovOptionService
.getOptions(this.lovType)
.pipe(debounceTime(500), takeUntil(this.destroy$))
.subscribe((res: Options[]) => {
this.lovOptionsResponse = res;
this.lovOptions = res;
this.loading = false;
this.cdr.detectChanges();
});
}
}
private getAllLovs(): void {
if (AllLOVs.length) return;
this.http
.get(${this.baseURL}api/data/v1/lovtype?pageNo=1&pageSize=999
)
.pipe(takeUntil(this.destroy$))
.subscribe((res: any) => {
AllLOVs = res.items;
});
}
private isObjectEmpty(obj: any) {
if (!obj) return true;
return Object.keys(obj).length === 0;
}
filterLovOptions(filterString: any): void {
this.lovOptions = this.lovOptionsResponse.filter((lov) =>
lov.text.toLowerCase().includes(filterString.toLowerCase())
);
this.cdr.detectChanges();
}
valueUpdate(value: any): void {
this.value = value;
this.valueChange.emit(value);
this.cdr.detectChanges();
// this.formioEvent.emit({
// eventName: 'refresh',
// });
}
checkBoxUpdate(index: number, event: any): void {
const isChecked = event.target.checked;
if (isChecked) {
this.value.push(this.lovOptions[index].value);
} else {
this.value.splice(this.value.indexOf(this.lovOptions[index].value), 1);
}
this.valueChange.emit(this.value);
this.cdr.detectChanges();
}
getValueForMultiSelect(): any {
return typeof this.value == 'string' ? [] : this.value;
}
}
export let AllLOVs: LovItems[] = [];
export const COMPONENT_OPTIONS: FormioCustomComponentInfo = {
type: 'casexLov',
selector: 'casex-lov',
title: 'LOV',
group: 'customBasic',
icon: 'fa-thin fa-bars',
editForm: editForm,
};
export function registerLovComponent(injector: Injector) {
if (!customElements.get(COMPONENT_OPTIONS.selector))
registerCustomFormioComponent(
COMPONENT_OPTIONS,
CustomLovComponent,
injector
);
}
export function editForm() {
const components: ExtendedComponentSchema[] = [
{
type: 'tabs',
key: 'tabs',
components: [
{
key: 'data',
components: [
// {
// weight: 0,
// type: 'checkbox',
// label: 'Multiple Values',
// tooltip: 'Allows multiple values to be entered for this field.',
// key: 'multiple',
// input: true,
// },
{
weight: 3,
type: 'select',
input: true,
key: 'customOptions.lovType',
label: 'Lov Type',
placeholder: 'enter lov type',
tooltip:
'Enter the LOV type to be used for this field. This is the LOV type that will be used to populate the dropdown list.',
validate: {
required: true,
},
dataSrc: 'custom',
valueProperty: 'value',
data: {
custom: function custom(context: any) {
return AllLOVs.map((lov) => {
return { label: lov.id, value: lov.id };
});
},
},
},
{
type: 'select',
label: 'View Type',
key: 'customOptions.viewType',
weight: 5,
placeholder: 'View Type',
tooltip: 'View Type will determine how the options will be shown',
input: true,
defaultValue: 'dropdownSingleSelect',
data: {
values: [
{
label: 'Dropdown (Single Select)',
value: 'dropdownSingleSelect',
},
{
label: 'Dropdown (Multi Select)',
value: 'dropdownMultiSelect',
},
{
label: 'Radio',
value: 'radio',
},
{
label: 'Checkbox',
value: 'checkbox',
},
],
},
},
{
type: 'select',
label: 'Default Value',
key: 'defaultValue',
weight: 8,
placeholder: 'Default Value',
tooltip:
'The Default Value will be the value for this field, before user interaction. Having a default value will override the placeholder text.',
input: true,
},
],
label: 'Data',
weight: 10,
},
],
},
{
type: 'hidden',
key: 'type',
},
];
return {
components: components,
};
}
`
`<div *ngIf="showUI">
Select an LOV Type to view options!
Select an LOV Type to view options!
<ng-template #singleSelectDropdown>
<kendo-dropdownlist
fillMode="outline"
[data]="lovOptions"
[value]="value"
textField="text"
valueField="value"
[valuePrimitive]="true"
[filterable]="true"
[disabled]="loading"
(valueChange)="valueUpdate($event)"
(filterChange)="filterLovOptions($event)"
`