angular
angular copied to clipboard
[Custom Components] Ability to optionally select multiple values in Custom Component
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
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)"
`