Implementing Cascading Dropdown Lists for Dynamic Field Enablement in a Custom Component

1 Answer 166 Views
DropDownList Form
Tejas
Top achievements
Rank 2
Iron
Iron
Iron
Tejas asked on 07 Jun 2023, 07:20 AM

I have created a custom DropDownLists component, but I am facing some issues with implementing cascading DropDownLists. Specifically, I need assistance in ensuring that when the billing type is set to "cash," the fields for "BILLING_CYCLE," "CREDIT_LIMIT," "CREDIT_BALANCE," and "INTEREST" are disabled. However, when a different option is selected for the billing type, those fields should be enabled. Could you please review the provided code and provide guidance on how to achieve this functionality?

 

 

import { Field, Form } from "@progress/kendo-react-form";
import { OkDropDownList } from "@elabassistcore/elab_components";
import { filterBy } from "@progress/kendo-data-query";
import { DropDownListFilterChangeEvent } from "@progress/kendo-react-dropdowns";
import { FieldRenderProps, FieldWrapper } from "@progress/kendo-react-form";
import { Error, Hint, Label } from "@progress/kendo-react-labels";
import React, { useEffect, useRef, useState } from "react";
import {
  FIELD_BILLING_CYCLE,
  FIELD_BILLING_TYPE,
  FIELD_CREDIT_BALANCE,
  FIELD_CREDIT_LIMIT,
  LABEL_BILLING_CYCLE,
  LABEL_BILLING_TYPE,
  LABEL_CREDIT_BALANCE,
  LABEL_CREDIT_LIMIT,
  LABEL_INTEREST,
} from "@constants/common-keys";
import {
  TEXT_FIELD_BILLING_TYPE,
  TEXT_FIELD_BILLING_CYCLE,
} from "@constants/client-keys";
import { FIELD_INTEREST } from "@constants/client_master-keys";
import { NumericTextBox } from "@progress/kendo-react-inputs";
import { Button } from "@progress/kendo-react-buttons";
//use a data
const billingTypeData = [
  { id: 1, billingType: "Prepaid" },
  { id: 2, billingType: "Postpaid" },
  { id: 3, billingType: "Cash" },
];
const billingCycleData = [
  { id: 1, billingCycle: "Daily" },
  { id: 2, billingCycle: "Weekly" },
  { id: 3, billingCycle: "Monthly" },
  { id: 4, billingCycle: "Quartly" },
];
// Custom Componentes
const CustomDropDownList = (fieldRenderProps: FieldRenderProps) => {
  const {
    validationMessage,
    touched,
    label,
    id,
    valid,
    disabled,
    hint,
    value,
    modified,
    wrapperStyle,
    name,
    onChange,
    data,
    ...other
  } = fieldRenderProps;
  const [FilteredData, setFilteredData] = useState([]);
  useEffect(() => {
    setFilteredData(data);
  }, [data]);
  const editorRef = useRef(null);
  const showValidationMessage: string | false | null =
    touched && validationMessage;
  const showHint: boolean = !showValidationMessage && hint;
  const hintId: string = showHint ? `${id}_hint` : "";
  const errorId: string = showValidationMessage ? `${id}_error` : "";
  const labelId: string = label ? `${id}_label` : "";
  const onFilterChange = (event: DropDownListFilterChangeEvent) => {
    setFilteredData(filterBy(data, event?.filter));
  };
  return (
    <FieldWrapper style={wrapperStyle}>
      <Label
        className="input-labels"
        id={labelId}
        editorRef={editorRef}
        editorId={id}
        editorValid={valid}
      >
        {label}
      </Label>
      <OkDropDownList
        ariaLabelledBy={labelId}
        ariaDescribedBy={`${hintId} ${errorId}`}
        id={id}
        disabled={disabled}
        onChange={onChange}
        value={value}
        onFilterChange={onFilterChange}
        filterable={true}
        data={FilteredData}
        {...other}
        name={name}
      />
      {showHint && <Hint id={hintId}>{hint}</Hint>}
      {showValidationMessage && <Error id={errorId}>{validationMessage}</Error>}
    </FieldWrapper>
  );
};
const FormNumericTextBox = (fieldRenderProps: FieldRenderProps) => {
  const {
    validationMessage,
    touched,
    label,
    id,
    valid,
    disabled,
    hint,
    value,
    defaultValue,
    ...others
  } = fieldRenderProps;
  const showValidationMessage: string | false | null =
    touched && validationMessage;
  const showHint: boolean = !showValidationMessage && hint;
  const hintId: string = showHint ? `${id}_hint` : "";
  const errorId: string = showValidationMessage ? `${id}_error` : "";
  return (
    <FieldWrapper>
      <Label
        className="input-labels"
        editorId={id}
        editorValid={valid}
        editorDisabled={disabled}
      >
        {label}
      </Label>
      <NumericTextBox
        ariaDescribedBy={`${hintId} ${errorId}`}
        valid={valid}
        id={id}
        disabled={disabled}
        value={value === 0 ? "" : value}
        {...others}
      />
      {showHint && <Hint id={hintId}>{hint}</Hint>}
      {showValidationMessage && <Error id={errorId}>{validationMessage}</Error>}
    </FieldWrapper>
  );
};
// Kendo Field us with Map Function
const FiedData = [
  {
    id: FIELD_BILLING_TYPE,
    name: FIELD_BILLING_TYPE,
    label: LABEL_BILLING_TYPE,
    data: billingTypeData,
    textField: TEXT_FIELD_BILLING_TYPE,
    onChange: (event: { target: { value: object[] } }) => ({
      value: event.target.value,
    }),
    component: CustomDropDownList,
  },
  {
    id: FIELD_BILLING_CYCLE,
    name: FIELD_BILLING_CYCLE,
    label: LABEL_BILLING_CYCLE,
    component: CustomDropDownList,
    onChange: (event: { target: { value: object[] } }) => ({
      value: event.target.value,
    }),
    data: billingCycleData,
    textField: TEXT_FIELD_BILLING_CYCLE,
  },
  {
    id: FIELD_CREDIT_LIMIT,
    name: FIELD_CREDIT_LIMIT,
    label: LABEL_CREDIT_LIMIT,
    component: FormNumericTextBox,
  },
  {
    id: FIELD_CREDIT_BALANCE,
    name: FIELD_CREDIT_BALANCE,
    label: LABEL_CREDIT_BALANCE,
    component: FormNumericTextBox,
  },
  {
    id: FIELD_INTEREST,
    name: FIELD_INTEREST,
    label: LABEL_INTEREST,
    component: FormNumericTextBox,
  },
];
function FormComponet() {
  const handleSubmit = (dataItem: any) => alert(JSON.stringify(dataItem));
  return (
    <Form
      initialValues={{ title: "" }}
      onSubmit={handleSubmit}
      render={(formRenderProps) => (
        <div>
          {FiedData.map((item, index: number) => (
            <div key={index} className="div-input-group">
              <Field
                id={item.id}
                name={item.name}
                label={item.label}
                component={item.component}
                textField={item.textField}
                data={item.data}
                onChange={item.onChange}
              />
            </div>
          ))}
          <Button
            className="k-button k-mt-5"
            disabled={!formRenderProps.allowSubmit}
            onClick={formRenderProps.onSubmit}
          >
            Submit
          </Button>
        </div>
      )}
    />
  );
}
export default FormComponet;

1 Answer, 1 is accepted

Sort by
0
Konstantin Dikov
Telerik team
answered on 09 Jun 2023, 06:26 AM

Hello Tejas,

For achieving the desired result you can use the formRenderProps and its valueGetter method for retrieving values of other fields within the context of the Form or if you pass its reference to a Field component, you can get and set values within that component directly.

Following is a very basic example demonstrating how you can pass a reference to the formRenderProps in a custom component and also, how you can determine the "disabled" state based on a different field value:

          <Field
            id={'size'}
            name={'size'}
            label={'T-Shirt Size'}
            component={FormMultiSelectSize}
            data={sizes}
            //the disabled property is changed based on the genderselected field value dynamically
            //the above line will disable the component if the selected gender value is "female"
            disabled={
              formRenderProps.valueGetter('genderselected')?.value == 'female'
            }

Hope this helps.

 

Regards,
Konstantin Dikov
Progress Telerik

As of R2 2023, the default icon type will be SVG instead of Font. See this blogpost for more information.
Tejas
Top achievements
Rank 2
Iron
Iron
Iron
commented on 16 Jun 2023, 05:34 AM

Thank you, Konstantin Dikov, for your invaluable assistance. Your expertise and guidance have been crucial in achieving success. I am truly grateful for your support and knowledge.
Tags
DropDownList Form
Asked by
Tejas
Top achievements
Rank 2
Iron
Iron
Iron
Answers by
Konstantin Dikov
Telerik team
Share this question
or