HTML code:
<div class="table-responsive">
<table id="dataTable" class="table table-hover table-separated">
<tbody>
<tr id="test-1">
<td class="test">
<form action="{{ url('/psy/update-test-status/'.$test->id) }}" method="POST" class="m-0">
<select name="status" class="form-control status_select">
<option class="text-success" value="active" selected>En ligne</option>
<option class="text-warning" value="inactive" >Inactif</option>
<option class="text-danger" value="canceled" >Annulé</option>
</select>
</form>
</td>
</tr>
<tr id="test-2">
<td class="test">
<form action="{{ url('/psy/update-test-status/'.$test->id) }}" method="POST" class="m-0">
<select name="status" class="form-control status_select">
<option class="text-success" value="active" selected>En ligne</option>
<option class="text-warning" value="inactive" >Inactif</option>
<option class="text-danger" value="canceled" >Annulé</option>
</select>
</form>
</td>
</tr>
<tr id="test-3">
<td class="test">
<form action="{{ url('/psy/update-test-status/'.$test->id) }}" method="POST" class="m-0">
<select name="status" class="form-control status_select">
<option class="text-success" value="active" selected>En ligne</option>
<option class="text-warning" value="inactive" >Inactif</option>
<option class="text-danger" value="canceled" >Annulé</option>
</select>
</form>
</td>
</tr>
</tbody>
</table>
</div>
JavaScript Code:
$(document).ready(function () {
// change color of selected element according to its value
function statusSelect(element) {
if ($(element).val() == 'active') {
$(element).removeClass('text-warning');
$(element).removeClass('text-danger');
$(element).addClass('text-success');
}
else if ($(element).val() == 'inactive') {
$(element).removeClass('text-success');
$(element).removeClass('text-danger');
$(element).addClass('text-warning');
}
else if ($(element).val() == 'canceled') {
$(element).removeClass('text-success');
$(element).removeClass('text-warning');
$(element).addClass('text-danger');
}
}
// Post form data and load the table again
function updateTestStatus(element) {
form = $(element).parent('form');
tr = form.closest('tr');
dest_url = form.attr('action');
$.ajax({
type:"POST",
url:dest_url,
data:form.serialize(),
dataType: 'json',
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
success: function(data){
if($.isEmptyObject(data.errors)){
$('#dataTable').load(document.URL + ' #dataTable');
statusSelect($(element));
}
else {
// code...
}
},
errors: function (data) {
// code...
}
});
}
$('select.status_select').each(function (elem) {
statusSelect($(this));
});
$('select.status_select').on('change', function (e) {
statusSelect($(this));
updateTestStatus($(this));
});
});
Actually, I have at least four problems:
- I'm not sure about how to order and/or imbricate functions
eachandon change - I can't load only
trelement in the ajax success callback: It works fine when loading the fulltablebut when I do$('#dataTable tr#test-1').load(document.URL + ' #dataTable tr#test-1');it loads thetrinside the previoustrinstead of replacing it. - The
statusSelectmethod (change color of select selected input text) works the first time but not after Ajax load anymore - The
updateTestStatusmethod (Ajax call then reload part of page) works the first time but not anymore after it.
EDIT : 3rd and 4th issues are now solved (The functions in success callback were executed before the load function has finished)
Updated code:
function statusSelect(element) {
if ($(element).val() == 'active') {
$(element).removeClass('text-warning');
$(element).removeClass('text-danger');
$(element).addClass('text-success');
}
else if ($(element).val() == 'inactive') {
$(element).removeClass('text-success');
$(element).removeClass('text-danger');
$(element).addClass('text-warning');
}
else if ($(element).val() == 'canceled') {
$(element).removeClass('text-success');
$(element).removeClass('text-warning');
$(element).addClass('text-danger');
}
}
function updateTestStatus(element) {
form = $(element).parent('form');
tr = form.closest('tr');
dest_url = form.attr('action');
$.ajax({
type:"POST",
url:dest_url,
data:form.serialize(),
dataType: 'json',
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
success: function(data){
if($.isEmptyObject(data.errors)){
var row_id = tr.attr('id');
$('#dataTable #'+row_id).load(document.URL + ' #dataTable #'+row_id, function() {
testStatus();
});
}
else {
// code...
}
},
errors: function (data) {
// code...
}
});
}
function testStatus () {
$('select.status_select').each(function (elem) {
statusSelect($(this));
});
$('select.status_select').on('change', function (e) {
statusSelect($(this));
updateTestStatus($(this));
});
}
testStatus();
});
I have one issue left: I want to be able to load only <tr> and not all the <table>...
$('#dataTable tr#test-1').load(document.URL + ' #dataTable tr#test-1'); gives me:
<table><tr id="test-1"><tr id="test-1">...</tr></tr></table>
EDIT 2: Solved!
It appears load method "appends inside" and does not "replace" as I believed. This line did the trick:
$('#dataTable #'+row_id).load(document.URL + ' #dataTable #'+row_id, function() {
$(this).children(':first').unwrap(); // This one
testStatus();
});
I was helped by this thread: How can I use jQuery.load to replace a div including the div
Final Edit
The ajax function was sometimes called several times because of the each. Here is how I solved it:
success: function(data){
if($.isEmptyObject(data.errors)){
var row_id = tr.attr('id');
$('#dataTable #'+row_id).load(document.URL + ' #dataTable #'+row_id, function() {
$(this).children(':first').unwrap();
$('#'+row_id+' select.status_select').on('change', function (e) {
statusSelect($(this));
updateTestStatus($(this));
});
$('select.status_select').each(function (elem) {
statusSelect($(this));
});
});
}
}