EBuzila EBuzila - 1 month ago 7
jQuery Question

jQuery before produces multiple instances

I have a

bootstrap
nav tabs and I want to add tabs dynamically with jQuery. When I click on a button, a
bootstrap modal
shows up where I can pick an option. Once I've selected one, an
ajax
call get the
id
of selected option, it search for full option object and then return the object as
json
. Then a new tab is added, with the name of the option. All good, but if I click one more time on "Add option", it returns me 2 tabs...and if I add one more...returns 3 tabs, an so on!
heres my code:
HTML:

<div id="select_opt" class="modal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close_op" data-dismiss="modal">&times;</button>
<h4 class="modal-title">{{ __('Choose option') }}</h4>
</div>
<div class="modal-body">
<select name="op" id="op">
@if (count($language->optionDescriptions))
@foreach ($language->optionDescriptions as $optionDescription)
<option value="{{ $optionDescription->option->id }}">{{ $optionDescription->name }}</option>
@endforeach
@endif
</select>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" id="select_new_opt" data-dismiss="modal">Select</button>
</div>
</div>

</div>












JS:

$('#add_opt').click(function () {
$('#select_opt').css('display', 'block');
$('.close_op').click( function () {
$('#select_opt').css('display', 'none');
});

$('#select_new_opt').click(function () {
var option_id = $('#op option:selected').val();

$.ajax({
dataType: 'json',
type: 'POST',
url: '{{ URL::to('options/getOption') }}',
data: { id : option_id, _token : $('input[name="_token"]').val() },
success: function (data) {
$('.nav.nav-tabs #add_option').before('<li class="active"><a data-toggle="tab" href="#option-'+option_id+'" data-attr-id="'+option_id+'">'+data.option.name+'</a></li>');
}
});
});


});


html TABS:

<div class="tab-content options_tab">
<div id="product" class="tab-pane fade in active">
<div class="form-group">
<label for="" class="control-label col-md-2">{{ __('Optiuni') }}</label>

</div>
</div>



Answer

You are bind event handler's instead the event handlers, hence on every click event of #add_opt element click handlers are added for .close_op and #select_new_opt element.

Move event binding outside the click handler.

$('#add_opt').click(function() {
    ....
});

$('.close_op').click(function() {
    ...
});

$('#select_new_opt').click(function() {
    ...
});

As you are generating elements dynamically, use Event Delegation with .on() delegated-events approach.

Example

$(document).on('click', ".close_op", function(){
    $('#select_opt').hide();
});

In place of document you should use closest static container.