0

In Firestore you can update fields in nested objects by a dot notation (https://firebase.google.com/docs/firestore/manage-data/add-data?authuser=0#update_fields_in_nested_objects). I wonder how to make that work in Typescript / Javascript.

For example the following object:

const user = {
    id: 1
    details: {
        name: 'Max',
        street: 'Examplestreet 38',
        email: {
            address: '[email protected]',
            verified: true
        }
    },
    token: {
        custom: 'safghhattgaggsa',
        public: 'fsavvsadgga'
    }
}

How can I update this object with the following changes:

details.email.verified = false;
token.custom = 'kka';

I already found that Lodash has a set function:

_.set(user, 'details.email.verified', false);

Disadvantage: I have to do this for every change. Is their already a method to update the object with an object (like firestore did)?

const newUser = ANYFUNCTION(user, {
    'details.email.verified': false,
    'token.custom' = 'kka'
});

// OUTPUT for newUser would be
{
        id: 1
        details: {
            name: 'Max',
            street: 'Examplestreet 38',
            email: {
                address: '[email protected]',
                verified: false
            }
        },
        token: {
            custom: 'kka',
            public: 'fsavvsadgga'
        }
    }

Does anyone know an good solution for this? I already found more solutions if I only want to change one field (Dynamically set property of nested object), but no solution for more than one field with one method

2 Answers 2

1

I think you are stuck with using a function but you could write it yourself. No need for a lib:

function set(obj, path, value) {
    let parts = path.split(".");
    let last = parts.pop();
    let lastObj = parts.reduce((acc, cur) => acc[cur], obj);
    lastObj[last] = value;
}

set(user, 'details.email.verified', false);

if what you want to do is merge 2 objects then it is a bit trickier:

function forEach(target, fn) {
    const keys = Object.keys(target);
    let i = -1;
    while (++i < keys.length) {
        fn(target[keys[i]], keys[i]);
    }
}

function setValues(obj, src) {
    forEach(src, (value, key) => {
        if (value !== null && typeof (value) === "object") {
            setValues(obj[key], value);
        } else {
            obj[key] = value;
        }
    });
}

let obj1 = {foo: {bar: 1, boo: {zot: null}}};
let obj2 = {foo: {baz: 3, boo: {zot: 5}}};

setValues(obj1, obj2);

console.log(JSON.stringify(obj1));
Sign up to request clarification or add additional context in comments.

1 Comment

After submitting my question I came up what a silly question I asked :D Thanks for your answer, yours is also a good one if someone not want to use lodash
0

One solution in combination with lodash _.set method could be:

function setObject(obj, paths) {
        for (const p of Object.keys(paths)) {
            obj = _.set(obj, p, paths[p]);
        }
        return obj;
}

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.