Javascript Replace - Dynamic Value of Replacement

2020-04-10 02:57发布

I have a template in a String and I want to replace a few of the placeholders with the values that I have in another string. For every placeholder that I replace, I also want to insert a break tag.

For eg if #ADDRESS2# is found in the template, I am using the following code to replace all its occurrences with value in string val.address2.

    template_html = template_html.replace(/#ADDRESS2#/g, '<br />'+ val.address_2);

However there are scenarios when the string val.address2 is empty. In that case, I do not want to insert the break tag.

So I changed my code as follows

    if( val.address_2.length > 0 ) {
        template_html = template_html.replace(/#ADDRESS2#/g, '<br />'+ val.address_2);
    } else {
        template_html = template_html.replace(/#ADDRESS2#/g, '');
    }

Is there a better way to write the above code as I have multiple Placeholders and for each Placeholder I have to write the code 2 times.

标签: javascript
7条回答
再贱就再见
2楼-- · 2020-04-10 03:16

You could take the value with a check.

template_html = template_html.replace(
    /#ADDRESS2#/g,
    val.address_2 && '<br />' + val.address_2
);

For more than one placeholder, you could take a dynamic approach and use same pattern for the search and replacements.

var val = { address_2: 'foo', country_1: 'bar' }
    template_html = 'Address: #ADDRESS2#\nCountry: #COUNTRY1#\nnothing: #NOTHING#'

template_html = template_html.replace(
    /#([^#]+)#/g,
    (_, group) => {
        var key = group.match(/^(\D+)(\d*)$/).slice(1).map(s => s.toLowerCase()).join('_');

        return (val[key] || '') && '<br />' + val[key];
     }
);
console.log(template_html);

For getting a smarter replacement, yoou could take the idea of same strings as tempate and for getting the data from an object. In this case, take the replacement value and take this as key for the object or take an empty string for unknown values.

var val = { ADDRESS2: 'foo', COUNTRY1: 'bar' }
    template_html = 'Address: #ADDRESS2#\nCountry: #COUNTRY1#\nnothing: #NOTHING#'

template_html = template_html.replace(
    /#([^#]+)#/g,
    (_, key) => (val[key] || '') && '<br />' + val[key]
);
console.log(template_html);

查看更多
成全新的幸福
3楼-- · 2020-04-10 03:18

The simplest change is to use the ternary operator like this:

template_html = template_html.replace(/#ADDRESS2#/g, ( val.address_2.length > 0 ) ? '<br />'+ val.address_2 : '');

Still not particularly elegant but a bit shorter than the original.

查看更多
够拽才男人
4楼-- · 2020-04-10 03:25

You mean, something like this:

template_html = template_html.replace(/#ADDRESS(\d+)#/g, function(address, number) {
    return val.hasOwnProperty('address_' + number)
        ? '<br />' + val['address_' + number]
        : '';
};

You should use the val.hasOwnProperty just in case that val.['address_' + number] contains a value like 0, false, '', undefined, NaN or other falsy values.
It makes sure the value is displayed anyway, because an undefined isn't the same as not having the property at all.

It also avoids to get a value from the prototype, just in case.

This is based on mplungjan's answer.


If this is undesirable, and you only want to show strings, try this:

template_html = template_html.replace(/#ADDRESS(\d+)#/g, function(address, number) {
    return val.hasOwnProperty('address_' + number)
    && val['address_' + number].length
    && (
        (typeof val['address_' + number]) === 'string'
        || val['address_' + number] instanceof String
    )
        ? '<br />' + val['address_' + number]
        : '';
};

All of this checking ensures that it is a non-empty string (or String instance, because new String() returns a string object).
Checking if it is an instance of String prevents issues due to typeof new String() returning object.

Arrays and array-like objects have a length attributes (e.g.: jQuery instance, NodeList, {length: 1}, [0] and similars), but you dont want to show them as strings.

查看更多
小情绪 Triste *
5楼-- · 2020-04-10 03:26

If the same logic should be applied for multiple address fields, then you might benefit from a helper function:

template_html = template_html
    .replace(/#CITY1#/g, PrefixBrIfNotEmpty(val.city_1))
    .replace(/#CITY2#/g, PrefixBrIfNotEmpty(val.city_2))
    .replace(/#CITY3#/g, PrefixBrIfNotEmpty(val.city_3))
    .replace(/#ADDRESS1#/g, PrefixBrIfNotEmpty(val.address_1))
    .replace(/#ADDRESS2#/g, PrefixBrIfNotEmpty(val.address_2))
    .replace(/#ADDRESS3#/g, PrefixBrIfNotEmpty(val.address_3));

function PrefixBrIfNotEmpty(str) {
    return str ? '<br />' + str : '';
}
查看更多
ら.Afraid
6楼-- · 2020-04-10 03:29

Perhaps you meant this?

var val = {
  "address_1": "Address 1",
  "address_2": "",
  "address_10": "Address 10",
}  
var template_html = `My address is #ADDRESS1# delivery address is #ADDRESS2# and billing is #ADDRESS10#`
template_html = template_html.replace(/#ADDRESS(\d+)#/g, function(addr, num) { 
  var str = val["address_"+num]; return str?str+"<br/>":""
})
console.log(template_html)

查看更多
ら.Afraid
7楼-- · 2020-04-10 03:33

You can use ternary operator (empty string evaluates to false)

template_html = template_html.replace(/#ADDRESS2#/g, val.address_2 ? '<br />'+ val.address_2 : '');
查看更多
登录 后发表回答