aToz
aToz

Reputation: 3

String to template string for array of object mapping

somewhere from the API data I am getting normal string like, “Hi ${person[0].name}” now this string I am converting into template string and getting replace its variables from array of object.

Here is snippet which I am trying to execute, and I am not getting expected output

const getObjPath = (path, obj, fallback = `$\{${path}}`) => {
    if (path && obj) return path.split('.').reduce((res, key) => res[key] || fallback, obj);
    return path;
};
const interpolate = (template, variables, fallback) => {
    const regex = /\${[^{]+}/g;
    if (template && variables) {
        return template.replace(regex, (match) => {
            let path = match.slice(2, -1).trim();
            path = path.split('|').map((item) => item.trim());
            const fieldValue = getObjPath(path[0], variables, fallback);
            if (fieldValue) return fieldValue;
            return path[1] || fallback;
        });
    }
    return template;
};

const data = { person: [{ name: 'John', age: 18 }] };
const a = interpolate('Hi ${person?.[0]?.name | text} (${person?.[0]?.age | text})', data);
console.log(a);

output: "Hi ${person?.[0]?.name} (${person?.[0]?.age})"

expected output: "Hi John 18"

Can someone tell me what I am doing wrong here?

Upvotes: 0

Views: 271

Answers (1)

trincot
trincot

Reputation: 350310

The problem is that your path splitting in getObjPath does not deal with square brackets in the path.

So replace this

path.split('.')

with:

path.match(/[^.[\]]+/g)

const getObjPath = (path, obj, fallback = `$\{${path}}`) => {
    if (path && obj) return path.match(/[^.[\]]+/g).reduce((res, key) => res[key] || fallback, obj);
    return path;
};
const interpolate = (template, variables, fallback) => {
    const regex = /\${[^{]+}/g;
    if (template && variables) {
        return template.replace(regex, (match) => {
            let path = match.slice(2, -1).trim();
            path = path.split('|').map((item) => item.trim());
            const fieldValue = getObjPath(path[0], variables, fallback);
            if (fieldValue) return fieldValue;
            return path[1] || fallback;
        });
    }
    return template;
};

const data = { person: [{ name: 'John', age: 18 }] };
const a = interpolate('Hi ${person[0].name | text} (${person[0].age | text})', data);
console.log(a);

Upvotes: 1

Related Questions