0

I got a problem with a bootstrap modal form and dynamic select options.

  • When I open the modal, there is an input and two select options.
  • One select is populating the second after a user check an option from the first select.

On the first load, the select options are working ok. When I submit the form (with Save button) and I reopen the modal, the first select gets the correct options but the second got double options. When I reload the page everything gets back to normal until I submit the form again.

$(document).ready(function () { var table = $('table.setting-groups'); var table_permissions = $('table.settings-groups-permissions'); var table_permissions_edit = $('table.settings-groups-permissions-edit'); var permissions = []; var dataArray = []; $('#addGroupModal').on('shown.bs.modal', function (e) { $('select#permission_category').each(function () { var $select = $(this); $select.empty().append('<option></option>'); $.ajax({ url: $select.attr('data-source') }).then(function (options) { options.map(function (option) { var $option = $('<option>'); $option .val(option[$select.attr('data-valueKey')]) .text(option[$select.attr('data-displayKey')]); $select.append($option); }); }); }); $('select#permission_category').change(function () { var category = $('select#permission_category').val(); if (category !== '') { $('select#permission_category_description').each(function () { var $select = $(this); $select.empty().append('<option></option>'); $.ajax({ url: $select.attr('data-source'), data: {category: category} }).then(function (options) { options.map(function (option) { var $option = $('<option>'); $option .val(option[$select.attr('data-valueKey')]) .text(option[$select.attr('data-displayKey')]); $select.append($option); }); }); }); } else { $('select#permission_category_description')[0].empty(); } }); $('select#permission_category_description').change(function () { var category = $('select#permission_category').val(); var description = $('select#permission_category_description').val(); var check = $.inArray(description, permissions) > -1; if (!check) { permissions.push(description); table_permissions.DataTable().row.add({ "category": category, "description": description }).draw(); } }); // Save permissions $('form#add-group').submit(function (e) { $('#savebtn').button('loading'); e.preventDefault(); var form = $(this); // Push table data (permissions) to form for submit $('<input>').attr({ type: 'hidden', id: 'permissions', name: 'permissions', value: permissions }).appendTo(form); $.ajax({ url: form.attr('action'), type: form.attr('method'), data: new FormData(this), dataType: 'json', processData: false, contentType: false, success: function (data) { $('#addGroupModal').modal('toggle'); swal( 'Επιβεβαίωση Καταχώριση', 'Η ομάδα δικαιωμάτων καταχωρήθηκε επιτυχώς', 'success' ).then(function () { permissions = []; dataArray = []; form[0].reset(); $('select#permission_category_description').empty(); table_permissions.DataTable().destroy(); table.DataTable().ajax.reload(); }); }, error: function (data) { swal( 'Αποτυχία Καταχώρισης', data.responseText, 'error' ) } }); }); // Remove row when you click X table_permissions.on('click', '.delete', function () { table_permissions.DataTable().row('.selected').remove().draw(false); }); }); $('#addGroupModal').on('hide.bs.modal', function (e) { // Clean forms / select / datatables / arrays on modal close $('select#permission_category_description').empty(); $('form')[0].reset(); table_permissions.DataTable().destroy(); permissions = []; dataArray = []; }); $('#editGroupModal').on('shown.bs.modal', function (e) { var id = $(e.relatedTarget).data('id'); $.post('../../custom/json/groups.php?view', {id: id}, function (arr) { $('input#group_name').val(arr.description); // Get existing permissions from groups dataArray = arr.data.map(function (value) { return value.description; }); }); $('select#permission_category_edit').each(function () { var $select = $(this); $select.empty().append('<option></option>'); $.ajax({ url: $select.attr('data-source') }).then(function (options) { options.map(function (option) { var $option = $('<option>'); $option .val(option[$select.attr('data-valueKey')]) .text(option[$select.attr('data-displayKey')]); $select.append($option); }); }); }); $('select#permission_category_edit').change(function () { var category = $('select#permission_category_edit').val(); if (category !== '') { $('select#permission_category_description_edit').each(function () { var $select = $(this); $select.empty().append('<option></option>'); $.ajax({ url: $select.attr('data-source'), data: {category: category} }).then(function (options) { options.map(function (option) { var $option = $('<option>'); $option .val(option[$select.attr('data-valueKey')]) .text(option[$select.attr('data-displayKey')]); $select.append($option); }); }); }); } else { $('select#permission_category_description_edit')[0].empty(); } }); $('select#permission_category_description_edit').change(function () { var category = $('select#permission_category_edit').val(); var description = $('select#permission_category_description_edit').val(); permissions = dataArray; var check = $.inArray(description, permissions) > -1; if (!check) { permissions.push(description); table_permissions_edit.DataTable().row.add({ "category": category, "description": description }).draw(); } }); var settingGroupsPermissionsEdit = { "destroy": true, "processing": true, "deferRender": true, "responsive": true, "select": true , "searching": false, "paging": false, "info": false, "ordering": false, "language": { "url": "/custom/js/data-tables/Greek.json" }, "ajax": "../../custom/json/groups.php?view&id=" + id, "dataSrc": "data", "columns": [ {data: "category", className: "text-center"}, {data: "description", className: "text-center"}, { data: null, className: "text-center btn-actions", render: function (data, type, row) { return '<a data-id="' + data.description + '" class="danger p-0 delete"><i class="ft-x font-medium-3 mr-2"></i></a>'; } } ] }; $('table.settings-groups-permissions-edit').DataTable($.extend(true, {}, settingGroupsPermissionsEdit, {})); // Save permissions $('form#edit-group').submit(function (e) { $('#editbtn').button('loading'); e.preventDefault(); var form = $(this); // Push table data (permissions) to form for submit $('<input>').attr({ type: 'hidden', id: 'permissions', name: 'permissions', value: permissions }).appendTo(form); $.ajax({ url: form.attr('action') + '&id=' + id, type: form.attr('method'), data: new FormData(this), dataType: 'json', processData: false, contentType: false, success: function (data) { $('#editGroupModal').modal('toggle'); swal( 'Επιβεβαίωση Ενημέρωσης', 'Η ομάδα δικαιωμάτων ενημερώθηκε επιτυχώς', 'success' ).then(function () { permissions = []; dataArray = []; form[0].reset(); $('select#permission_category_description_edit').empty(); table_permissions_edit.DataTable().destroy(); table.DataTable().ajax.reload(); }); }, error: function (data) { swal( 'Αποτυχία Ενημέρωσης', data.responseText, 'error' ) } }); }); // Remove row when you click X table_permissions_edit.on('click', '.delete', function () { var row_desc = table_permissions_edit.DataTable().rows('.selected').data().pluck('description')[0]; permissions = remove(permissions, row_desc); // remove element from posted permissions array table_permissions_edit.DataTable().row('.selected').remove().draw(); }); }); $('#editGroupModal').on('hide.bs.modal', function (e) { // Clean forms / select / datatables / arrays on modal close $('select#permission_category_description_edit').empty(); $('form')[0].reset(); table_permissions_edit.DataTable().destroy(); permissions = []; dataArray = []; }); // Delete group table.on('click', '.swal-delete', function () { var id = $(this).data('id'); swal({ title: 'Διαγραφή', text: 'Είστε σίγουρος/η οτι θέλετε να διαγράψετε την ομάδα δικαιωμάτων;', type: 'warning', showCancelButton: true, confirmButtonColor: '#0CC27E', cancelButtonColor: '#FF586B', confirmButtonText: 'Ναι', cancelButtonText: 'Όχι' }).then(function (isConfirm) { if (isConfirm) { $.post("../../custom/json/groups.php?delete", {id: id}, function (data) { swal( 'Επιβεβαίωση Διαγραφής', 'Η ομάδα δικαιωμάτων διαγράφηκε επιτυχώς', 'success' ).then(function () { table.DataTable().ajax.reload(); }); }); } }).catch(swal.noop); }); // Remove element from an array function remove(array, value) { return array.filter(function (element) { return element !== value; }); } });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <!-- BEGIN ADD GROUP MODAL--> <div class="modal fade text-left" id="addGroupModal" role="dialog" aria-labelledby="addGroupModal" style="display: none;" aria-hidden="true"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <form id="add-group" action="/custom/json/groups.php?add" method="post" class="form form-horizontal" autocomplete="off" enctype="multipart/form-data"> <div class="modal-header bg-medi white"> <h4 class="modal-title" id="addGroupModal"><i class="ft-list font-medium-3 mr-2"></i> Προσθήκη Νέας Ομάδας</h4> </div> <div class="modal-body mt-1"> <fieldset class="form-group floating-label-form-group row"> <label class="col-md-4 label-control mt-1" for="group_name">Όνομα Ομάδας: </label> <div class="col-md-5"> <input type="text" id="group_name" class="form-control" name="group_name"> </div> </fieldset> <fieldset class="form-group floating-label-form-group row"> <label class="col-md-4 label-control" for="permission_category">Κατηγορία</label> <div class="col-md-5"> <select id="permission_category" name="permission_category" class="form-control" data-source="/custom/json/groups.php?permission-category" data-valueKey="category" data-displayKey="category"> </select> </div> </fieldset> <fieldset class="form-group floating-label-form-group row"> <label class="col-md-4 label-control" for="permission_category_description">Πρόσβαση</label> <div class="col-md-5"> <select id="permission_category_description" name="permission_category_description" class="form-control" data-source="/custom/json/groups.php?permission-description" data-valueKey="description" data-displayKey="description"> </select> </div> </fieldset> <div class="table-responsive"> <table class="table table-condensed table-bordered table-sm base-style table-hover full-width settings-groups-permissions"> <thead class="bg-medi text-white text-center"> <tr> <th>Κατηγορία</th> <th>Πρόσβαση</th> <th></th> </tr> </thead> </table> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Κλείσιμο</button> <button type="submit" class="btn btn-medi white" id="savebtn" data-loading-text="Αποθήκευση...">Αποθήκευση</button> </div> </form> </div> </div> </div> <!-- END ADD GROUP MODAL--> <!-- BEGIN EDIT GROUP MODAL--> <div class="modal fade text-left" id="editGroupModal" role="dialog" aria-labelledby="editGroupModal" style="display: none;" aria-hidden="true"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <form id="edit-group" action="/custom/json/groups.php?edit" method="post" class="form form-horizontal" autocomplete="off" enctype="multipart/form-data"> <div class="modal-header bg-medi white"> <h4 class="modal-title" id="editGroupModal"><i class="ft-list font-medium-3 mr-2"></i> Επεξεργασία Ομάδας</h4> </div> <div class="modal-body mt-1"> <fieldset class="form-group floating-label-form-group row"> <label class="col-md-4 label-control mt-1" for="group_name">Όνομα Ομάδας: </label> <div class="col-md-5"> <input type="text" id="group_name" class="form-control" name="group_name" disabled> </div> </fieldset> <fieldset class="form-group floating-label-form-group row"> <label class="col-md-4 label-control" for="permission_category_edit">Κατηγορία</label> <div class="col-md-5"> <select id="permission_category_edit" name="permission_category" class="form-control" data-source="/custom/json/groups.php?permission-category" data-valueKey="category" data-displayKey="category"> </select> </div> </fieldset> <fieldset class="form-group floating-label-form-group row"> <label class="col-md-4 label-control" for="permission_category_description_edit">Πρόσβαση</label> <div class="col-md-5"> <select id="permission_category_description_edit" name="permission_category_description" class="form-control" data-source="/custom/json/groups.php?permission-description" data-valueKey="description" data-displayKey="description"> </select> </div> </fieldset> <div class="table-responsive"> <table class="table table-condensed table-bordered table-sm base-style table-hover full-width settings-groups-permissions-edit"> <thead class="bg-medi text-white text-center"> <tr> <th>Κατηγορία</th> <th>Πρόσβαση</th> <th></th> </tr> </thead> </table> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Κλείσιμο</button> <button type="submit" class="btn btn-medi white" id="editbtn" data-loading-text="Αποθήκευση...">Αποθήκευση</button> </div> </form> </div> </div> </div> <!-- END EDIT GROUP MODAL-->

Any suggestions ? I can't find where is the issue that causes js to run twice on select populate options. Thank you in advance

UPDATE: The 2nd select option is doubled on modal show not on form submit.

3
  • I empty the $select on Line 4 Commented Sep 11, 2019 at 11:09
  • You need to empty the select as well for the second select box. From: $select.append($option); -> $select.empty().append($option); Commented Sep 11, 2019 at 11:10
  • 2
    Sounds like your ".on('<event>', ....)" -callbacks are stacking up. Check your code on how many times you run over each "on" -method call. To clear the binding you can use the jquery-off-method as decribed here: api.jquery.com/off Commented Sep 11, 2019 at 11:50

1 Answer 1

1
+50

Because you bind $('select#permission_category').change inside $('#addGroupModal').on('shown.bs.modal' handler so each time your modal show, it will bind $('select#permission_category').change another time. That's why when you open the modal second time, the 2nd select option is doubled and will be tripled on third time...

You can solve it by:

Option 1: Move $('select#permission_category').change to be outside of $('#addGroupModal').on('shown.bs.modal' handler.

Option 2: Remove $('select#permission_category') change handler using .off() when closing modal or before bind it in $('#addGroupModal').on('shown.bs.modal' handler.

Option 3: Create all options first then use .html() instead of .append() to set the html contents of select (this still bind change multiple time but the options is not multipled)

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

1 Comment

Tried Option 1, but its not helpfull. On Option 2 I added $('select#permission_category').off() and $('select#permission_category_description').off().empty() and It worked !! Thank you all

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.