Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Custom Components] Ability to optionally select multiple values in Custom Component #1055

Open
muneebahmad0600 opened this issue Feb 29, 2024 · 4 comments

Comments

@muneebahmad0600
Copy link

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.

image

when I select Multi-select in View Type dropdown and try to select the default value I get this.

image

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!

{{ lov.text }}

Select an LOV Type to view options!

{{ lov.text }}

<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)"

`
@muneebahmad0600
Copy link
Author

@travist would appreciate a response on this.

@gyanendrasinghpanwar
Copy link

@muneebahmad0600 If i remember correctly, this has to do with the property multiple. I presume u need to set it true in custom component.

@muneebahmad0600
Copy link
Author

HI @gyanendrasinghpanwar, sorry for replying after a long time.. got sidetracked.
I am taking 'multiple' as Input and marking it as true when viewType is 'Multiselect'.
the problem is, even if I set the value as an array i.e. ["PH"], when the component rebuilds it gives the value as a string i.e. "PH". hence mapping this with a dropdown that accepts an array is causing issue..
Also the original error below the component is still coming.

image

image

image

would appreciate any urgent help I can get.

@muneebahmad0600
Copy link
Author

Hi @gyanendrasinghpanwar @travist @peterblazejewicz @randallknutson.
Reaching out again to see if anyone can help on this.
Also, I have a requirement for which I need to a dropdown of the current form Components, same as we get on "Redraw On".
Any ideas? any help will be much appriciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants