0

I have a fields array with objects and I'm trying to loop this array:

fields: [
    {
        name: "seasonId",
        type: "select",
        label: "Season ID",
        placeholder: "Select a season id...",
        icon: "id",
        value: "",
        errors: "",
        required: true,
        disabled: true,
        selectOptions: [],
    },
    {
        name: "callTime",
        type: "time",
        label: "Scheduling Call Times",
        placeholder: "Select a time...",
        value: "",
        errors: "",
        required: true,
        disabled: true,
    },
];

To update its values AND append additional objects:

Incoming values:

"fieldValues": {
  "callTimes": [
    "5:45 pm",
    "6:15 pm",
    "6:30 pm",
    "7:00 pm"
  ],
  "selectedSeasonId": "20192020",
  "seasonIds": [
    "20192020",
    "20202021",
    "20212022",
  ]
}

Update field function:

const updateField = (currentField, fieldValues) => {
  switch(currentField.name) {
    case "seasonId":
      return {
        ...currentField,
        selectOptions: fieldValues.seasonIds,
        value: fieldValues.selectedSeasonId,
        disabled: false
      };
    case "callTime":
      const callTimes = fieldValues.callTimes.map((value, key) => ({
        ...currentField,
        name: key <= 0 ? "callTime" : `callTime-${Date.now()}`,
        label: key <= 0 ? "Scheduling Call Times" : "",
        value,
        required: key <= 0,
        disabled: false,
      }));

      return { 
        ...callTimes 
      };
  }
}

And then invoke the function above like so:

const updatedFields = fields.map(field => updateField(field, event));

However, I'm not getting the desired result.

Actual output:

[
  '0': {
    disabled: false
    errors: ""
    icon: "id"
    label: "Season ID"
    name: "seasonId"
    placeholder: "Select a season id..."
    required: true
    selectOptions: ["20192020", "20202021", "20212022"]
    type: "select"
    value: "20192020"
  },
  '1': {
         '0': {  
           disabled: false
           errors: ""
           label: "Scheduling Call Times"
           name: "callTime"
           placeholder: "Select a call time..."
           required: true
           style: {width: "100%"}
           type: "time"
           value: "5:45 pm"
         },
         '1': {
           disabled: false
           errors: ""
           label: ""
           name: "callTime-1565388886669"
           placeholder: "Select a call time..."
           required: false
           style: {width: "100%"}
           type: "time"
           value: "6:15 pm"
         },
         '3': { ... },
         '4': { ... }
      }
];

Expected output:

[
  '0': {
    disabled: false
    errors: ""
    icon: "id"
    label: "Season ID"
    name: "seasonId"
    placeholder: "Select a season id..."
    required: true
    selectOptions: ["20192020", "20202021", "20212022"]
    type: "select"
    value: "20192020"
  },
  '1': {
    disabled: false
    errors: ""
    label: "Scheduling Call Times"
    name: "callTime"
    placeholder: "Select a call time..."
    required: true
    style: {width: "100%"}
    type: "time"
    value: "5:45 pm"
  },
  '2': {
     disabled: false
     errors: ""
     label: ""
     name: "callTime-1565388886669"
     placeholder: "Select a call time..."
     required: false
     style: {width: "100%"}
     type: "time"
     value: "6:15 pm"
  },
  '3': { ... },
  '4': { ... }
];

Any ideas on how I can update values and append additional objects to my fields array? The callTimes array of string values within the field object is dynamic (can contain 1 string or many), so I can't hard code anything.

const fields = [
    {
        name: "seasonId",
        type: "select",
        label: "Season ID",
        placeholder: "Select a season id...",
        icon: "id",
        value: "",
        errors: "",
        required: true,
        disabled: true,
        selectOptions: [],
    },
    {
        name: "callTime",
        type: "time",
        label: "Scheduling Call Times",
        placeholder: "Select a time...",
        value: "",
        errors: "",
        required: true,
        disabled: true,
    },
];

const fieldValues = {
  "callTimes": [
    "5:45 pm",
    "6:15 pm",
    "6:30 pm",
    "7:00 pm"
  ],
  "selectedSeasonId": "20192020",
  "seasonIds": [
    "20192020",
    "20202021",
    "20212022",
  ]
};


const updateField = (currentField, event) => {
  switch(currentField.name) {
    case "seasonId":
      return {
        ...currentField,
        selectOptions: fieldValues.seasonIds,
        value: fieldValues.selectedSeasonId,
        disabled: false
      };
    case "callTime":
      const callTimes = fieldValues.callTimes.map((value, key) => ({
        ...currentField,
        name: key <= 0 ? "callTime" : `callTime-${Date.now()}`,
        label: key <= 0 ? "Scheduling Call Times" : "",
        value,
        required: key <= 0,
        disabled: false,
      }));

      return { 
        ...callTimes 
      };
  }
};

const updatedFields = fields.map(field => updateField(field, event));

console.log(updatedFields);

1 Answer 1

1

Using reduce instead of map, I believe I am getting the right output:

const updateField = (result, currentField) => {
  switch (currentField.name) {
    case 'seasonId':
      return [
        ...result,
        {
          ...currentField,
          selectOptions: fieldValues.seasonIds,
          value: fieldValues.selectedSeasonId,
          disabled: false
        }
      ]
    case 'callTime':
      const callTimes = fieldValues.callTimes.map(...);
      return [
        ...result,
        ...callTimes
      ]
  }
}
const updatedFields = fields.reduce(updateField, [])

Since your callTime case was returning multiple objects in an array, map wouldn't work well in this case as you need to push/add these objects individually to the "final" array, hence this return:

case 'callTime':
  const callTimes = fieldValues.callTimes.map(...);
  return [
    ...result,
    ...callTimes
  ]

Also, your callTimes came out to be an array, and you tried to spread its items into an object:

case "callTime":
  const callTimes = fieldValues.callTimes.map(...); // array
  return { 
    ...callTimes 
  };

This is why you were getting an unexpected/weird outcome.

Here's a demo with the fix:


Since you asked in the comments how to pass fieldValues to the reducer function since they are being imported from another file, you can do the following:

const updateField = (result, currentField, fieldValues) => {...}

const updatedFields = fields.reduce(
  (result, field) => updateField(result, field, fieldValues), 
  []
)

Everything else stays the same.

Here's another demo:

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.