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.