Insert variable in regular expression

Asked

Viewed 1,430 times

0

I need to change the name of the inputs after they are cloned. For example: order-recipient-name[0] would be order-recipient-name[1] and from there on.

What I tried to:

var current_counter = block.data('count');
var new_counter = current_counter + 1;

block.html(function(i, block) {
    return block.replace(/\[0\]/g, '['+new_counter+']');
});

Now I need to inform the variable instead of the 0. But when I change to:

return block.replace(`/\[${current_counter}\]/g`, '['+new_counter+']');

Does not work. Eslint returns an error:

Unnecessary escapeCharacter: [ no-Useless-escape

  • But because you want to replace "[N]" for "[N]"... Would not replace "[0]" for "[N]"?

  • @fernandosavio made the correction in the code.

  • Pq does not arrow the input name with $(seletor).attr('name', 'order-recipient-name['+new_counter+']')? I think it would be simpler.

  • @Sam because they are various inputs with patterns of different names.

2 answers

3


Basically, inside a string template, the character \ must be escaped, being written as \\. See the difference:

let current_counter = 1;
console.log(`/\[${current_counter}\]/g`); // imprime "/[1]/g"
console.log(`/\\[${current_counter}\\]/g`); // imprime "/\[1\]/g"

But that alone is not enough. /[1]/g is the literal form of a regular expression: the bars at the beginning and end are delimiters and are not part of the regex itself, and the g is one of many flags that can be used to change the behavior of the same (in this case, in a replace it serves to replace all occurrences, so in your case it does not seem to be really necessary, since you just want to replace an occurrence).

Only in your case, you need to dynamically assemble a string that corresponds to an expression, so the way to do this is by passing the string to the constructor of RegExp. The difference is that in this case the string should not have the bars at the beginning and end, and the flag g is passed separately in the second parameter:

let current_counter = 1;
let regex = new RegExp(`\\[${current_counter}\\]`, 'g');
let novo_valor = 'teste[1]'.replace(regex, `[${current_counter + 1}]`);
console.log(novo_valor); // teste[2]

  • 1

    As always, good answer. I just don’t understand why AP is using Regex, so it can pass a string and avoid compiling a regex unnecessarily...

  • @fernandosavio Yeah, I liked your solution of having a input model, but maybe in the case of the AP he does not always have the [0] available, I don’t know... Without more context, it’s hard to know...

  • 1

    Exactly, I formulated my answer without knowing what it is block. Only that there is a detail, if it is using PHP just that all have name="order-recipient-name[]".. and there, no need for freshness in JS

  • 1

    Anyway, without more information I can only leave these comments in the answer chosen to help someone in the future..

1

Supposing block is a string, the method String.prototype.replace() takes as first parameter a regex OR a string.

If the first parameter is a string, the first occurrence of the received substring is replaced.

So you don’t need to insert a variable into Regex, just concatenate a string with the number:

let new_counter = 9
"order-recipient-name[0]".replace("[0]", `[${new_counter}]`)
// "order-recipient-name[9]"

Example

let input_modelo = document.getElementById('modelo');
let container = input_modelo.parentElement;
let button = document.getElementById('add-new');

function clone_input() {
    let new_input = input_modelo.cloneNode();
    new_input.id = null;  // `id` deve ser único
    
    // Atualiza o `name` do input com o contador de elementos
    let count = container.querySelectorAll('.super-input').length;
    new_input.name = new_input.name.replace('[0]', `[${count}]`);
    
    // Apenas para mostrar qual é o `name` do input
    new_input.value = new_input.name;
    
    container.appendChild(new_input);
}

button.addEventListener('click', clone_input);
input.super-input {
    display: block;
    margin: 0.5rem;
}
<button id="add-new">Add</button>
<fieldset>
  <input id="modelo" name="order-recipient-name[0]" class="super-input" value="order-recipient-name[0]">
</fieldset>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.