Single dropdown filtering for Datatable - datatables
I've been struggling for a few days now, trying to get a single dropdown to filter my table. Upon selection of the eraId, the columns should be refreshed to only show the columns of the selected eraId.
This is how my tables looks like:
I've read a lot of examples on Datatables website or forums but I can't seem to find something working.
I have managed to create a dropdown menu containing the different EraIds as filter (I have simplified the example below with only 3 eraIds) but after selecting an entry in the dropdown, the table gets empty and the column list is not refreshed.
I think the problem is that I first retrieve the columns names, based on the eraId and then draw the table accordingly, displaying only the resources from the specific eraId. I have tried several things but did not manage.
Ideally I should callback getPlayerResourceTable with the selected eraId or update the column list with the resources on the selected eraId.
Javascript:
var columns = [];
function getPlayerResourceTable($selectedEraId) {
$.ajax({
type: "POST",
url: "./graphs.php",
data: { call_function : 'getResourceTableColumns', eraId: $selectedEraId},
success: function (data) {
data = JSON.parse(data);
columnNames = Object.keys(data.data);
for (var i in data.data) {
columns.push({data: data.data[i],
title: data.data[i]});
}
$('#playerResourceTable').DataTable( {
processing: true,
serverSide: false,
filter: true,
columns: columns,
ajax: {
url: './graphs.php',
type: 'POST',
data: { call_function: 'playerResourceTable', column_fields : data.data, eraId: $selectedEraId}
},
initComplete: function () {
this.api().columns( 0 ).every( function () {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo( $("#playerResourceTablesWrapper .dataTables_filter"))
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column.search( this.value ).draw();
} );
select.append( '<option value="1">Era 1</option>' )
select.append( '<option value="2">Era 2</option>' )
select.append( '<option value="3">Era 3</option>' )
} );
}
});
}
});
}
$(document).ready(function() {
$selectedEraId = 1;
getPlayerResourceTable($selectedEraId);
} );
PHP:
getResourceTableColumns returns the column list with query similar to SELECT columnName FROM ages WHERE eraId = ?
playerResourceTable returns the resources for each column (type of resource) with query similar to SELECT ".$field_list." FROM user_resources
I also thought of removing WHERE eraId = ? in my MySQL query and filtering the columns on the client side but no luck either.
I eventually ended up separating both functions and destroying/re-creating the table when changing Era.
function getColumns($selectedEraId) {
var columns = [];
$.ajax({
type: "POST",
url: "./graphs.php",
data: { call_function : 'getResourceTableColumns', eraId: $selectedEraId},
success: function (data) {
data = JSON.parse(data);
for (var i in data.data) {
columns.push({data: data.data[i],
title: data.data[i]});
}
if ( $.fn.dataTable.isDataTable( '#playerResourceTable' ) ) { // If the table already exists, detroy it before creating it again
$('#playerResourceTable').DataTable().destroy();
}
getPlayerResourceTable($selectedEraId, columns); // Will recreate the table with the new columns
}
});
}
function getPlayerResourceTable($selectedEraId, columns_to_show) {
$city_id = 91;
$playerResourceTable = $('#playerResourceTable').DataTable( {
processing: true,
serverSide: false,
filter: true,
columns: columns_to_show,
ajax: {
url: './graphs.php',
type: 'POST',
data: { call_function: 'playerResourceTable', column_fields : columns_to_show, city_id : parseInt($city_id)}
},
initComplete: function () {
this.api().columns( 0 ).every( function () {
var column = this;
var select = $('<select id="selectEraId" ><option value=""></option></select>')
.appendTo( $("#playerResourceTablesWrapper .dataTables_filter"))
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column.search( this.value ).draw();
} );
dropdown_string = getEraDropdown($selectedEraId);
} );
$('#selectEraId').on('change', function() {
$selectedEraId = this.value;
columns_to_show = getColumns($selectedEraId);
});
}
});
}
Related
How to create location select box in cshtml page without model
I want to create a select box for the location field, in which if one types any letter should call API and fetch location details in the dropdown I tried the below code but didn't work <select class="js-data-example-ajax form-control" id="FilterLocation"></select> #Html.Hidden("FilterLocation", new { id = "locationId" }) In the script written below code function setLocation() { $('.js-data-example-ajax').select2({ ajax: { type: 'PUT', url: function (params) { return '/api/GoogleCustomSearch/getLocation?matchingName=' + params.term }, delay: 250, data: function (params) { var query = { } // Query paramters will be ?search=[term]&page=[page] return query; }, processResults: function (data) { data = JSON.parse(data); let results = [] if (data.location !== null) { data.location.forEach((e) => { results.push({ id: e, text: e }) }) } return { results: results }; } }, placeholder: "Search" }) $('.js-data-example-ajax').on('change',function(e){ var selVal = $('#FilterLocation').val() $('#locationId').val(selVal) //getZipCodeForDynamic(selVal) }) var $newOption = $("<option selected='selected'></option>") $("#FilterLocation").append($newOption).trigger('change'); } Dropdown options are not getting with above code.
Here is a working demo for select2: View: <select id="mySelect2" class="js-data-example-ajax" style="width:200px"></select> js: $('#mySelect2').select2({ ajax: { type: 'PUT', url: "GetSelect2Data", delay: 250, data: function(params) { var query = { search: params.term, } // Query parameters will be ?search=[term] return query; }, processResults: function(data) { //data = JSON.parse(data); let results = [] if (data.location !== null) { data.location.forEach((e) => { results.push({ id: e, text: e }) }) } return { results: results }; } }, placeholder: "Search" }); model: public class Select2Model { public List<string> Location { get; set; } } action: [HttpPut] public ActionResult GetSelect2Data(string Search) { return Json(new Select2Model() { Location = new List<string> { "a"+Search,"b" + Search, "c" + Search } }); } result:
Datatables onchange event for input field
I have input fields in my project with a special class (date_input_field). On change these fields format the data that user has entered. The problem is that these fields work fine absolutely everywhere EXCEPT DataTables. I tried rowCallback in my datatable itself, but it didn't help. Why? And how can I fix that? $(".date_input_field").change(function () { ...format the data }); var table2 = $("#stopsTable").DataTable({ ajax: { url: "/api/stops/" + confirmationId, dataSrc: "" }, columns: [ { data: "date1", render: function (data) { var arr = data.split("T")[0].split("-"); return "<input class='form-control date_input_field' type='text' value='" + arr[2] + "-" + arr[1] + "-" + arr[0]+"'/>" ;}} ], order: [[0, "asc"]], scrollY: '50vh', scrollCollapse: true, paging: false, rowCallback: function (row, data) { $(row).css("cursor", "pointer"); $(".date_input_field").change(function () { $(this).attr("value", "01"); }); } });
Sorry for stupid question. I tried the code below and it works. rowCallback: function (row, data) { $(row).css("cursor", "pointer"); $(row).on("change", ".date_input_field", function () { var input = $(this); input.val("1111111111"); }); }
when the user edits the input on the cell this will console log the edited field with its input id rowCallback is the function which can trigger / perform on any cell inside the datatable var datatable = $('#datatable').DataTable({ rowCallback: function (row, data) { $(row).on("change", ".edit_qty_class", function () { var input = $(this); input.attr('value', input.val()) console.log() console.log($(this).attr('id'), input.val()) }); }, columns: [{ data: "id", render: function(data, type, full, meta) { return meta.row + 1 } }, { data: "id", title:"QTY SEND", render: function(data, type, full, meta) { var dataID = 'edit_qty_' + data.id return `<input type="number" id="`+dataID+`" name="`+dataID+`" class="edit_qty_class" value="0">` } }, })
Knockout-Kendo Chart - remove and add series
My project is MVC 5, I am using the following to generate a chart with multiple series: HTML: <button data-bind="click: addItem">Add</button> <button data-bind="click: removeItem">Remove</button> <div data-bind="kendoChart2: { title: { text: 'Graph Sample' }, series: seriesConfig,tooltip: {visible: true,template: '#= series.name #: #= value #'} , seriesDefaults: { type: 'line',style: 'smooth'}}"> </div> Javascript var MainViewModel = function () { var self = this; this.Systolic = ko.observableArray([]); this.Diastolic = ko.observableArray([]); this.HeartRate= ko.observableArray([]); $.ajax({ type: "GET", url: '/Charts/GetChart', contentType: "application/json; charset=utf-8", async: false, cache: false, dataType: "json", success: function (result) { //Diastolic if (result && result.Systolic.length > 0) { for (var i = 0; i < result.Systolic.length; i++) { self.Systolic.push(result.Systolic[i].Systolic); } }; .... }, error: function (err) { alert(err.status + " : " + err.statusText); }}); this.seriesConfig = ko.observableArray([ {name: "Systolic", data: this.Systolic()}, {name: "Diastolic",data: this.Diastolic()}]); this.addItem = function() { this.seriesConfig.push({ name: "Heart Rate", data: this.HeartRate() }); }; this.removeItem = function() { this.seriesConfig.remove({ name: "Diastolic", data: this.Diastolic() }); }; }.bind(this); ko.kendo.bindingFactory.createBinding( { name: "kendoChart", bindingName: "kendoChart2", watch: { data: function(value) { ko.kendo.setDataSource(this, value); }, series: function(value) { this._sourceSeries = value; this.refresh(); this.redraw();} } }); window.viewModel = new MainViewModel(); ko.applyBindings(window.viewModel); The chart works great, however can't add or remove series? Note: the addItem works, I get the value of the new series: series: function (value) { alert(value[2].name); this.seriesConfig = value; this.refresh(); this.redraw(); } I also tried load all series then use the following hide a series: $("#kendoChart").getKendoChart().options.series[1].visible = false; $("#kendoChart").getKendoChart().redraw(); Does not work, I think the chart name does not register.
I am not familiar with knockout-kendo, just with knockout in general, so if fixing obvious problem as described below will not work, you might need to refresh bindings. Looking at this example however this is not needed, so most likely you got caught by a simple fact that array's remove performs simple == comparison and it fails to find equal object in the array. Here is a simplified example (although you might know it already, but just in case): var a="abc"; var b="abc"; var aa = [1,2,3,"a","b","c"]; var data1 = {name: a, data: aa}; var data2 = {name: b, data: aa}; now, comparison a==b returns true and clearly data slots are the same, however data1==data2 is false. That is because it's a different object. So in your example in removeItem you create and pass a new object to remove, not the one in the array, so == comparison fails and nothing is removed as that newly created object isn't in your observable array. I suggest comparing the name only similar to item.age < 18 comparison from knockout.js documentation on observable arrays: this.seriesConfig.remove( function (item) { return item.name == "Diastolic"; } ) I believe, this should do the trick.
How to chain get and map the result with lodash?
I've got a list I'm trying to pull an object from using _.get but following that selection I need to loop over the object to create a new property. So far I've been successful using a combination of _.get and _.map as shown below but I'm hoping I can use _.chain in some way. var selected = _.get(results, selectedId); return _.map([selected], result => { var reviews = result.reviews.map(review => { var reviewed = review.userId === authenticatedUserId; return _.extend({}, review, {reviewed: reviewed}); }); return _.extend({}, result, {reviews: reviews}); })[0]; Is it possible to do a transform like this using something other than map (as map required me to break this up/ creating an array with a solo item inside it). Thank you in advance!
I can see that you're creating unnecessary map() calls, you can simply reduce all those work into something like this: var output = { reviews: _.map(results[selectedId], function(review) { return _.defaults({ reviewed: review.userId === authenticatedUserId }, review); }) }; The defaults() method is similar to extend() except once a property is set, additional values of the same property are ignored. var selectedId = 1; var authenticatedUserId = 1; var results = { 1: [ { userId: 1, text: 'hello' }, { userId: 2, text: 'hey' }, { userId: 1, text: 'world?' }, { userId: 2, text: 'nah' }, ] }; var output = { reviews: _.map(results[selectedId], function(review) { return _.defaults({ reviewed: review.userId === authenticatedUserId }, review); }) }; document.body.innerHTML = '<pre>' + JSON.stringify(output, 0, 4) + '</pre>'; <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Column Visibility is not restored from a saved state via stateLoadCallback
I have added the Column Visibility button to choose to show or hide certain columns. I'm saving the state in a database, I call the stateSaveCallback function via a click on a button. I cant find documentation about retrieving data this way, so I just link to the page and pass variables to get the data back from the database, and then load that using stateLoadCallback. Now all this works fine, EXCEPT the column visibility is not restored. It is in the JSON data being returned though. Here is my full code: $(document).ready(function() { $.extend( jQuery.fn.dataTableExt.oSort, { "date-uk-pre": function (a){ return parseInt(moment(a, "DD/MM/YYYY").format("X"), 10); }, "date-uk-asc": function (a, b) { return a - b; }, "date-uk-desc": function (a, b) { return b - a; } }); var edit_date_col_num = $('th:contains("Edit Date")').index(); var entry_date_col_num = $('th:contains("Entry Date")').index(); var table = $('.mainTable').DataTable( { pageLength: 50, colReorder: true, stateSave: true, columnDefs: [ { "type": "date-uk", targets: [ edit_date_col_num, entry_date_col_num ] } ], dom: 'Blfrtip', buttons: [ 'copy', 'csv', 'excel', 'print', { extend: 'colvis', collectionLayout: 'fixed four-column', postfixButtons: [ 'colvisRestore' ] } ], <?php $id = $this->input->get('id'); $action = $this->input->get('action'); if(isset($action) && $action == 'load' && isset($id) && $id != '') : ?> "stateLoadCallback": function (settings) { var o; // Send an Ajax request to the server to get the data. Note that // this is a synchronous request since the data is expected back from the // function $.ajax( { "url": EE.BASE + "&C=addons_modules&M=show_module_cp&module=ion&method=state_save&action=load&id=<?php echo $id;?>", "async": false, "dataType": "json", "success": function (response) { response = JSON.parse(response); o = response; } }); return o; }, <?php endif; ?> initComplete: function (settings) { this.api().columns().every( function () { var column = this; var select = $('<select><option value=""></option></select>') .appendTo( $(column.footer()).empty() ) .on( 'change', function () { var val = $.fn.dataTable.util.escapeRegex( $(this).val() ); column .search( val ? '^'+val+'$' : '', true, false ) .draw(); } ); column.data().unique().sort().each( function ( d, j ) { select.append( '<option value="'+d+'">'+d+'</option>' ) } ); } ); // Need to re-apply the selection to the select dropdowns var cols = settings.aoPreSearchCols; for (var i = 0; i < cols.length; i++) { var value = cols[i].sSearch; if (value.length > 0) { value = value.replace("^", "").replace("$",""); console.log(value); $("tfoot select").eq(i).val(value); } } }, } ); // Save a datatables state by clicking the save button $( ".save_state" ).click(function(e) { e.preventDefault(); table.destroy(); $('.mainTable').DataTable( { colReorder: true, stateSave: true, "stateSaveCallback": function (settings, data) { var save_name = $('.save_name').val(); // Send an Ajax request to the server with the state object $.ajax( { "url": EE.BASE + "&C=addons_modules&M=show_module_cp&module=ion&method=state_save&action=save&save_name="+save_name, "data": data, "dataType": "json", "type": "POST", "success": function (response) { //console.log(response); } } ); }, }); //table.state.save(); window.location.replace(EE.BASE + "&C=addons_modules&M=show_module_cp&module=ion&method=applications"); }); $( ".clear_state" ).click(function(e) { e.preventDefault(); table.state.clear(); window.location.replace(EE.BASE + "&C=addons_modules&M=show_module_cp&module=ion&method=applications"); }); } ); Here is the saved JSON with several visible false in the beginning (which are visible once loaded): {"time":"1449338856556","start":"0","length":"50","order":[["0","asc"]],"search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"},"columns":[{"visible":"false","search":{"search":"","smart":"false","regex":"true","caseInsensitive":"true"}},{"visible":"false","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"false","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"false","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"false","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}}],"ColReorder":["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70"]} Thanks
In my case datatables rejects old data according to "stateDuration" and "time" properties.. Solution: ignore state duration "stateSave": true, "stateDuration": -1, Above case: "visible":"false" may should be "visible":false
After a while of debugging this myself here's what worked for me.. This issue is that all the values in your JSON are strings and they need to be of correct datatypes for the datatables plugin. Within the "stateSaveCallback" ajax request to save your state I did the following to the json string and then it saved all the values properly which then loaded the state as it should. "stateSaveCallback": function (settings, data) { var save_name = $('.save_name').val(); // Send an Ajax request to the server with the state object $.ajax( { "url": EE.BASE + "&C=addons_modules&M=show_module_cp&module=ion&method=state_save&action=save&save_name="+save_name, //"data": data, "data": JSON.stringify(data), // change to this.. "dataType": "json", "type": "POST", "success": function (response) { //console.log(response); } } ); },