The problem
Need dynamic string templating with variable substitution
The solution
function template(string, data) {
return string.replace(/\$\{([^}]+)\}/g, (match, key) => {
const keys = key.trim().split('.');
let value = data;
for (const k of keys) {
if (value && typeof value === 'object' && k in value) {
value = value[k];
} else {
return match; // Return original if key not found
}
}
return value != null ? value : '';
});
}
// Alternative: With fallback values and functions
function advancedTemplate(string, data, options = {}) {
const { fallback = '', allowFunctions = false } = options;
return string.replace(/\$\{([^}]+)\}/g, (match, expression) => {
try {
// Handle simple property access
const keys = expression.trim().split('.');
let value = data;
for (const key of keys) {
if (value && typeof value === 'object' && key in value) {
value = value[key];
} else {
return fallback;
}
}
// Execute if it's a function (if allowed)
if (allowFunctions && typeof value === 'function') {
return value();
}
return value != null ? value : fallback;
} catch {
return fallback;
}
});
}Parameters
stringstringTemplate string with ${variable} placeholders
dataobjectData object for substitution
Put it to work
const templateString = 'Hello, ${name}! You have ${messages.unread} unread messages.';
const data = {
name: 'John',
messages: {
unread: 5,
total: 20
}
};
console.log(template(templateString, data));
// "Hello, John! You have 5 unread messages."
// With nested objects
const userTemplate = 'User: ${user.name} (${user.id}) - Status: ${user.status}';
const userData = {
user: {
id: 123,
name: 'Alice',
status: 'active'
}
};
console.log(template(userTemplate, userData));
// "User: Alice (123) - Status: active"
// Advanced template with functions
const funcTemplate = 'Generated ID: ${generateId}';
const funcData = {
generateId: () => Math.random().toString(36).substr(2, 9)
};
console.log(advancedTemplate(funcTemplate, funcData, { allowFunctions: true }));
// "Generated ID: abc123def"