automatix automatix - 1 month ago 9
Javascript Question

How to make jQuery update the internal elements counter on remove()?

I have a list of elements and want to add and remove elements. The list should always contain minimum

x
and maximum
y
elements. An element contains of a text input field and a button to remove the element . Add succeeds on cklick on the add button +.

The problem is, that jQuery
remove()
seems not to decrease the internal elements counter or maybe doesn't really removes, but only hides the element.

Sure, I could use a variable for counting, but it should also work without it.

How to make jQuery really remove the element and decrease the internal elements count on remove()?




Background info:

I have a form with an input fields collection
parameter_set
. It should contain minimum
1
test input field and maximum
5
fields.

field and buttons

const PARAMETERS_MIN_NUMBER = 1;
const PARAMETERS_MAX_NUMBER = 5;
$(document).ready(function() {
addParameterButton = $('#add-parameter-button');
addParameterButton.on('click', addParameter);
removeParameterButton = $('.remove-parameter-button');
removeParameterButton.on('click', removeParameter);
});
function addParameter() {
var currentCount = $('#my-form .parameters fieldset:first > fieldset').length;
console.log('add start | current:' + currentCount);
var template = $('#my-form .parameters fieldset:first > span').data('template');
template = template.replace(/__index__/g, currentCount);
if (currentCount < PARAMETERS_MAX_NUMBER) {
$('#my-form .parameters fieldset:first').append(template);
removeParameterButton = $('.remove-parameter-button');
removeParameterButton.on('click', removeParameter);
}
currentCount = $('#my-form .parameters fieldset:first > fieldset').length;
console.log('add stop | current:' + currentCount);
return false;
}
function removeParameter() {
var currentCount = $('#my-form .parameters fieldset:first > fieldset').length;
console.log('remove start | current:' + currentCount);
if (currentCount > PARAMETERS_MIN_NUMBER) {
$(this).prev().remove();
$(this).remove();
}
currentCount = $('#my-form .parameters fieldset:first > fieldset').length;
console.log('remove stop | current:' + currentCount);
return false;
}

<label class="parameters">
<span>parameter set</span>
<fieldset>
<fieldset>
<label>
<span>parameter</span>
<input type="text" value="" class="form-control field-expression" name="my_form[parameter_set][parameters][0][expression]">
</label>
<button value="remove an include parameter" class="btn btn-default button-remove remove-parameter-button" name="parameter_set[parameters][0][remove-parameter]" type="button">&ndash;</button>
</fieldset>
<span data-template="the complete fieldset like above with a text-input-field & a remove-button ..."></span>
</fieldset>
</label>


In principle it works, but
remove()
doesn't lead to a reducing of the internal elements counter and brakes the whole logic:

initial fields number = $('#my-form .parameters fieldset:first > fieldset').length = 1
click on <kbd>+</kbd>
=> fields number = $('#my-form .parameters fieldset:first > fieldset').length = 2
click on <kbd>-</kbd>
=> fields number = $('#my-form .parameters fieldset:first > fieldset').length = 2 -- and not 1!

Answer

You're counting fieldsets, and it looks like you're only removing the button and the label

To recap, you have HTML templates looking like

<fieldset>
    <label>
       <span>...</span>
       <input ...>
    </label>
    <button value="remove">&ndash;</button>
</fieldset>

When you click the button you do

$(this).prev().remove();
$(this).remove();

That removes the button and the label, not the fieldset, so the next time you check the length with

var currentCount = $('#my-form .parameters fieldset:first > fieldset').length;

You still have the same amount of fieldsets.
The solution is probably to just remove the fieldset all together

function removeParameter(e) {
    e.preventDefault();

    var currentCount = $('#my-form .parameters fieldset:first > fieldset').length;

    if (currentCount > PARAMETERS_MIN_NUMBER) {
        $(this).closest('fieldset').remove();
    }

    currentCount = $('#my-form .parameters fieldset:first > fieldset').length;

    console.log('remove stop | current:' + currentCount);
}
Comments