0

I have an object like this

myObj = {
    "strPattern": "Name: #name#<br>Surname: #sname#<br>Location: #loc#",
    "name": "John",
    "sname": "Doe",
    "loc": "LA"
}

Now I need a function which will take my object and return it as a string with the help of its pattern.

Expected Result : "Name: John<br>Surname: Doe<br>Location: LA"

I couldn't do it with JavaScript's replace method and I dont know how to do it. Thank for your help.

By the way, number of subStrs can be dynamic. For example there are 3 subStrings in this example but it can be 5 or 10 for other objects. #age#, #gender#, etc...

1
  • I know you have an answer, but you may want to look at actual templating engines like ejs, handlebars, etc Commented Feb 1, 2014 at 9:29

5 Answers 5

2

You can loop to an objects properties using the for (var key in myObj) structure. In every loop the key variable holds the name of each property and you can access its value with the myObj[key] variable.

An example of how you could use in your scenario could be like this.

var myObj = {
    "strPattern": "Name: #subStr1#<br>Surname: #subStr2#<br>Location: #subStr3#",
    "subStr1": "John",
    "subStr2": "Doe",
    "subStr3": "LA"
};

var html = myObj["strPattern"];

for (var key in myObj) {
   var obj = myObj[key];
    if(key !== "strPattern") {
        html = html.replace("#" + key + "#",obj);
    }
}

jQuery('#result').html(html);

I also made a jsfiddle with it.

Edit: As @Andreas mentioned in a comment, the order of accessing the properties is not guaranteed, I adjusted my code snippet accordingly.

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

6 Comments

@Andreas -- Although the specs say no, every implementation says yes. But even so, I don't like this. var html = myObj.strPattern with if( key === 'strPattern' ){ continue; } is better.
your replace should be html.replace( new RegExp( '#' + key + '#', 'g' ), obj ) ) to allow for multiple instances of the same pattern
@zyklus But it is not guaranteed and therefor you shouldn't rely on. I'm not aware of the current situation but there were times when the order was implemented differently (v8 - Issue 164)
@Andreas -- Eh, you can rely on it if you need to, as long as you're aware that it may break somewhere, at some point (even if that's very unlikely). Your page is more likely to break because JS is disabled than because of this
|
2

The following function can be used to improve performances. However, it's useless if you don't need to use the template multiple times.

function compile(tpl) {
    tpl = tpl.split(/#(.*?)#/);
    return Function('return [' + tpl.map(function (v, i) {
        if (i % 2) return 'this["' + v + '"]';
        return v && '"' + v.replace(/"/g, '\\"') + '"';
    }).join(',') + '].join("");');
}

Usage example :

var myObj = {
    "strPattern": "Name: #name#<br>Surname: #sname#<br>Location: #loc#",
    "name": "John",
    "sname": "Doe",
    "loc": "LA"
};

myObj.strPattern = compile(myObj.strPattern).call(myObj);

More interesting :

var tpl = '#first# #last#',
    compiled = compile(tpl);

compiled.call({ first: 'John', last: 'Doe' }); // "John Doe"
compiled.call({ first: 'Walter', last: 'White' }); // "Walter White"

More details here : https://stackoverflow.com/a/20886377/1636522.

Comments

0

Another way to approach this, that works through only the replacements that appear in the string, would be:

var Stringify = function(obj){
  return obj.strPattern.replace(/#([a-z]+)#/gi, function(match,group){
    return obj[group] || match;
  });
};

var str = Stringify({
  "strPattern": "Name: #name#<br>Surname: #sname#<br>Location: #loc#",
  "name": "John",
  "sname": "Doe",
  "loc": "LA"
});

This also could be of interest to those wanting to use string.replace(pattern, function).

When did all browsers start supporting the String.replace(regexp, replacement_function)?

Comments

0
myObj = {
    "strPattern": "Name: #subStr1#<br>Surname: #subStr2#<br>Location: #subStr3#",
    "subStr1": "John",
    "subStr2": "Doe",
    "subStr3": "LA"
}
function patternMatcher(myObj){
  strp = myObj.strPattern;
  pattern = strp.match(/#(.*?)#/g);

  for (key in pattern){
    origKey = pattern[key].substr(1,pattern[key].length-2);
    strp =  strp.replace(pattern[key],myObj[origKey])
  }
return strp;
}

console.log(patternMatcher(myObj)); 

Here's Your Code running example link

Comments

0
function getFilled(myObj){
  pattern = myObj.strPattern.match(/#(.*?)#/g);
  for (key in pattern){
    myObj.strPattern =  myObj.strPattern.replace(pattern[key],myObj[pattern[key].substr(1,pattern[key].length-2)])
  }
return myObj.strPattern;
}

console.log(getFilled(myObj)); 

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.