0

I've got a nested object with child objects and arrays. Something like this:

const documents = {
    invoice: {
        documentID: '_e4564',
        displayName: '2019-02-03',
        url: 'https://www.urltoinvoice.com'
    },

    conditions: {
        documentID: '_e9365',
        displayName: 'Conditions company x',
        url: 'https://www.urltoconditions.com'
    },

    reminders: [
        {
            documentID: '_e4364',
            displayName: 'First reminder',
            url: 'https://www.urltofirstreminder.com'
        },
        {
            documentID: '_e0254',
            displayName: 'Second reminder',
            url: 'https://www.urltosecondreminder.com'
        },
    ]
}

I'm trying to create a new array of objects to use in a select box. The child objects need the same properties but with an updated displayName based on the document type. So, for example, reminder: First reminder .

Currently, this is my code:

const newArray = [];
this.addDocumentToArray(documents, newArray);

and the addDocumentToArray function:

addDocumentToArray = (documents, arr) => {
    Object.entries(documents).forEach(([key, val]) => {
        if (Array.isArray(val)) {
            this.addDocumentToArray(val, arr);
        } else {
            arr.push({ documentID: val.documentID, displayName: `${key}: ${val.displayName}` });
        }
    });
}

The output at this point is an array that looks like this:

0: {documentID: "_e4564", displayName: "invoice: 2019-02-03"}
1: {documentID: "_e9365", displayName: "conditions: Conditions company x"}
2: {documentID: "_e4364", displayName: "0: First reminder"}
3: {documentID: "_e0254", displayName: "1: Second reminder"}

Almost ok but the key of the reminders is 0 and 1. How can I get reminder (or reminders) as key?

Thore
  • 1,918
  • 2
  • 25
  • 50

2 Answers2

2

You can add third optional parameter to function labelKey. You are passing that parameter only if your value is array and it will use that value as key in else part

addDocumentToArray = (documents, arr, labelKey) => {
        Object.entries(documents).forEach(([key, val]) => {
            if (Array.isArray(val)) {
                this.addDocumentToArray(val, arr, key);
            } else {
                arr.push({ documentID: val.documentID, displayName: `${labelKey || key}: ${val.displayName}` });
            }
        });
    }
chriss
  • 669
  • 4
  • 9
0

I really like chriss' answer, so I'll try to write an alternative:

let currentKey = null;
addDocumentToArray = (documents, arr) => {
Object.entries(documents).forEach(([key, val]) => {
    if (Array.isArray(val)) {
        let prevKey = currentKey;
        currentKey = key;
        this.addDocumentToArray(val, arr);
        currentKey = prevKey;
    } else {
        arr.push({ documentID: val.documentID, displayName: `${currentKey || key}: ${val.displayName}` });
    }
    });
}
xenocratus
  • 116
  • 4
  • Sry this might not work. It will work for data example above. But in case you first loop reminders and than conditions, currentKey would be set by reminders. When you are setting conditions, current key is already set and nothing cleared it to undefined. Instead of currentKey = prev you would need to set it to undefined Generally using global variables is not encouraged – chriss Mar 03 '19 at 23:03
  • ? If you first hit reminders, currentKey is set to reminders and after the call ends it's set back to null (if you prefer undefined instead of null, that works as well) – xenocratus Mar 03 '19 at 23:06
  • Yes actually you are right it will still work, you are resetting key properly – chriss Mar 03 '19 at 23:13