I have a DataTables table coming from a database. I want to have a dropdown enabled when I select rows from the dataset. The dropdown will be populated with every option from that column.
It has been suggested that this be done using rowCallback, but I haven't been able to figure out how to create the editable fields for the columns by row once the checkbox is enabled.
The function, on select would cause that row's Class and Category cells to become dropdown menus populated with all of the existing options in Class and Category to choose from.
HTML
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/select/1.3.0/css/select.dataTables.min.css" media="screen" />
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/buttons/1.5.6/css/buttons.dataTables.min.css" media="screen" />
<script charset="utf8" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script charset="utf8" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<script charset="utf8" src="https://cdn.datatables.net/select/1.3.0/js/dataTables.select.min.js"></script>
<script charset="utf8" src="https://cdn.datatables.net/buttons/1.5.6/js/dataTables.buttons.min.js"></script>
<script charset="utf8" src="https://cdn.datatables.net/buttons/1.5.6/js/buttons.flash.min.js"></script>
<script charset="utf8" src="https://cdn.datatables.net/buttons/1.5.6/js/buttons.html5.min.js"></script>
<script charset="utf8" src="https://cdn.datatables.net/buttons/1.5.6/js/buttons.print.min.js"></script>
<script charset="utf8" src="https://editor.datatables.net/extensions/Editor/js/dataTables.editor.min.js"></script>
</head>
</html>
<body>
<div class="container">
<table id="samples" class="display nowrap compact hover dt-left" width="100%"></table>
</table>
</form>
<script type="text/javascript" charset="utf8" src="JS/datatables.js"></script>
</body>
Jquery
$(document).ready( function () {
var table = $('#samples').DataTable( {
"processing": true,
"serverSide": false,
"pageLength": -1,
"lengthMenu": [[100, 250, 500, -1], [100, 250, 500, "All"]],
ajax: "datatables.php",
columns: [
{data: '',
defaultContent: '0',
visible: false },
{data: '',
defaultContent: '',
orderable: false,
className: 'select-checkbox',
targets: 1
},
{title : 'Sample Name', 'className': 'dt-left', data: 1},
{title : 'Region/Program', 'className': 'dt-left', data: 2},
{title : 'Class', 'className': 'dt-left', data: 3},
{title : 'Category', 'className': 'dt-left', data: 4},
{title : 'QC Concerns', 'className': 'dt-left', data: 5}
],
select: {
style: 'multi',
},
order: ([[ 4, 'asc' ], [ 5, 'asc' ], [ 3, 'asc' ]]),
orderFixed: [0, 'desc'],
dom: 'Bfrtip',
buttons: [
{
extend: 'excel',
text: '<span class="fa fa-file-excel-o"></span> Download (ALL) or (SELECTED)',
exportOptions: {
columns: [ 2, 5 ],
modifier: {
search: 'applied',
order: 'applied'
}
}
},
{
text: 'Use Selected Library',
action: function ( e, dt, node, config) {
alert( 'This buton needs to pass the Sample Name and Category columns to php.' );
}
},
{
text: 'Upload Predefined Library',
action: function ( e, dt, node, conf ) {
alert( 'This button needs to allow a csv file to be uploaded and passed to php.' );
}
}
]
} );
table.on( 'select', function ( e, dt, type, indexes ) {
if ( type === 'row' ) {
var row = table.row( dt );
table.cell({ row: row.index(), column: 0 } ).data( '1' );
table.draw();
}
});
table.on( 'deselect', function ( e, dt, type, indexes ) {
if ( type === 'row' ) {
var row = table.row( dt );
table.cell({ row: row.index(), column: 0 } ).data( '0' );
table.draw();
}
});
} );
Data sample
const srcData = [
{Name: '752', Region: '7', Class : 'unknown', Category : 'unknown', QC_Concerns: 'yes'},
{Name: 'North 5th', Region: 'NWA', Class : 'unknown', Category : 'square', QC_Concerns: 'yes'},
{Name: 'Elmdale', Region: '6', Class : 'back', Category : 'circle', QC_Concerns: ''},
{Name: 'Rosebud', Region: '7', Class : 'back', Category : 'triangle', QC_Concerns: ''},
{Name: 'Letterkenny', Region: 'GO', Class : 'back', Category : 'square', QC_Concerns: ''},
{Name: '632nd', Region: 'GO', Class : 'front', Category : 'ball', QC_Concerns: ''},
{Name: 'Water', Region: '4', Class : 'front', Category : 'ball', QC_Concerns: ''},
{Name: 'Dirt', Region: '1', Class : 'front', Category : 'mermaid', QC_Concerns: ''},
];
I failed to comprehend your sample data structure, so I demonstrated the way of how it can be done, using my own:
//table source data
const srcData = [{
id: 1,
item: 'apple',
category: 'fruit'
}, {
id: 2,
item: 'banana',
category: 'fruit'
}, {
id: 3,
item: 'carrot',
category: 'vegie'
}, {
id: 4,
item: 'raspberry',
category: 'berry'
}, {
id: 5,
item: 'potato',
category: 'vegie'
}
];
//DataTable initialization
const dataTable = $('#mytable').DataTable({
dom: 't',
data: srcData,
select: 'multi',
columns: Object.keys(srcData[0]).map(key => {
return {
title: key,
data: key
}
})
});
//grab all the unique sorted data entries from the necessary row
const category = dataTable.column(2).data().unique().sort();
//Row click handler
dataTable.on('deselect', (event, row, type, index) => writeCell($(row.node()).find('select')));
dataTable.on('select', (event, row, type, index) => $(row.node()).find('td:eq(2)').html('<select>' + category.reduce((options, item) => options += `<option value="${item}" ${item == row.data().category ? 'selected' : ''}>${item}</option>`, '') + '</select>'));
//Drop down menu stop event propagation
$('#mytable').on('click', 'tbody td select', event => event.stopPropagation());
//Write dropdown value into table
var writeCell = dropdown => {
const currentRow = dataTable.row(dropdown.closest('tr'));
const rowData = currentRow.data();
rowData.category = dropdown.val();
currentRow.remove();
dataTable.row.add(rowData).draw();
};
tbody tr:hover {
background: lightgray !important;
cursor: pointer;
}
tbody tr.selected {
background: gray !important;
}
<!doctype html>
<html>
<head>
<script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/select/1.3.0/js/dataTables.select.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/select/1.3.0/css/select.dataTables.min.css">
</head>
<body>
<table id="mytable"></table>
</body>
</html>
This is going to add the ddl on your 3rd column for all the values in that column.
initComplete: function () { // After DataTable initialized
this.api().columns([2]).every(function () {
/* use of [2] for third column. Leave blank - columns() - for all.
Multiples? Use columns[0,1]) for first and second, e.g. */
var column = this;
var select = $('<select><option value=""/></select>')
.appendTo($('.datatable .dropdown .third').empty()) /* for multiples use .appendTo( $(column.header()).empty() ) or .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>')
});
}); // this.api function
} //initComplete function
});
});
$(window).resize(function () {
$('.datatable').removeAttr('style');
});
How can I change my jQuery autocomplete to use an Id instead of my values?
I would like to display the list of names but send a search using the Id value. Now it is working properly with the names but I think it will be more effective if it tries to find a unique value as an ID.
$.getJSON('Dashboard/CompaniesWithId', function (data) {
$.each(data, function (i, item) {
sellers[i] = item.Name;
sellersID[i] = item.Id;
});
}).error(function () {
console.log("error loading seller to the autocomplete");
});
$("#searchSeller").autocomplete({
messages: {
noResults: 'No sellers with this name',
},
minLength: 2,
delay: 500,
source: sellers,
});
you can add a hidden field and use the on select event to set the value of the hidden field to the selected id
http://api.jqueryui.com/autocomplete/#event-select
you can also use selection data with format [{value: 'value', label: 'label'}] but using this way, the field will show the id instead of the label
var availableTags = [
{id: 1, label: "ActionScript"},
{id: 2, label: "Ruby"},
{id: 3, label: "Scala"},
{id: 4, label: "Scheme"}
];
availableTags2 = [
{value: 1, label: "ActionScript"},
{value: 2, label: "Ruby"},
{value: 3, label: "Scala"},
{value: 4, label: "Scheme"}
];
$( "#a" ).autocomplete({
source: availableTags,
select: function( event, ui ) {
$('#tosend').val(ui.item.id);
}
});
$( "#b" ).autocomplete({
source: availableTags2
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script
src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
crossorigin="anonymous"></script>
id to send<br>
<input type="text" name="tosend" id="tosend"><br><br>
type below<br>
<input id="a"><br>
<br>
<br>
using value instead of id<br>
<input id="b">
I don't know anything about your back-end. But assuming it is accepting IDs for your search parameters, will changing the source value to sellersID resolve your issue? You also have that extra comma after sources. It will cause you problems.
$("#searchSeller").autocomplete({
messages: {
noResults: 'No sellers with this ID.',
},
minLength: 2,
delay: 500,
source: sellersID
});
Good day all.
I have a html page, page.html, which loads an iframe, called iframe.html.
I have Select2 into page.html and there is a <select class='selectme'> into iframe.html.
I'm using this js to fire Select2 FROM page.html:
var jFrame = function (selector) { return $(selector, $("iframe").contents()); };
OurBigWrapper = {
"setup":{
"init":function(){
console.log("wrapper,setup,init");
var data = [{ id: 0, text: 'enhancement' }, { id: 1, text: 'bug' }, { id: 2, text: 'duplicate' }, { id: 3, text: 'invalid' }, { id: 4, text: 'wontfix' }];
jFrame(".countries").select2(
{
data: data /*,
formatSelection : this.formatSelection.bind(this)*/
}
);
}
}
}
while on the iframe.html page the code is like this:
<select class="countries">
</select>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
parent.OurBigWrapper.setup.init();
});
</script>
What I obtain is that the Select gets the data properly, but once clicked, the select only "change" the little arrow on the right, indicating the "opened option panel" but no option actually shows up.
interesting enough, if I delete the select2 css, this is what I obtain:
and here, clicking on the select and selecting another option, is what I see:
someone has any kind of clue of what is going on and how I can prevent it to happen?
<script>
$(function ($) {
$("button").on("click", function (evt) {
var jFrame = function (selector) { return $(selector, $("iframe").contents()); };
var data = [{ id: 0, text: 'enhancement' }, { id: 1, text: 'bug' }, { id: 2, text: 'duplicate' }, { id: 3, text: 'invalid' }, { id: 4, text: 'wontfix' }];
jFrame(".selectme").select2(
{
data: data
}
);
});
})
</script>
</head>
<body>
<iframe id="myframe" src="iframe.html"></iframe>
<button type="button">click</button>
</body>
and
<body>
<select class="selectme"></select> i
</body>
</html>
I have added dynamically a textbox to the bottom of the ul as an option. When I try to type inside the focus is lost. If I remove the e.stopPropagation() and the use clicks on the textbox, then the list closes.
How can I type inside my custom textbox txtCategory the same way it allows typing on the 'Search' box without closing the list? The txtCategory has value '2' when loaded.
Here is the fiddle
Script
<script type="text/javascript">
var customOption = "<li class='multiselect4-item multiselect-filter' value='0'><div class='input-group'><input class='xxx' id='txtCategory' value='2'><input type='button' id='btnAddOption' value='Add'></div></li>";
$(document).ready(function () {
//$("#theChildx").hide();
$('#example-post-checkboxName').multiselect({
enableFiltering: true,
enableClickableOptGroups: true,
enableCollapsibleOptGroups: true,
includeSelectAllOption: true,
onDropdownShow: function (select, container) {
//var siz = parseInt($('#theParentx').height(),5) + parseInt($('#theParentx .multiselect-container').height(), 10) + parseInt($('#theChildx').height(),7);
//var w = $('#theParentx .multiselect-container').width();
//$('#theChildx').css({ 'top': siz + "px", 'width': w }).show();
},
onDropdownHide: function (event) {
//$("#theChildx").hide();
},
templates: {
divider: '<li class="multiselect-item divider"></li>',
liGroup: '<li class="multiselect-item group"><label class="multiselect-group"></label></li>'
}
});
var data = [{
title: 'First group',
children: [{ label: 'Cheese', value: 'cheese' , selected: true},
{ label: 'Tomatoes', value: 'tomatoes', selected: false, "attributes": {"some-attribute": 1, "another-attribute": false } }]
}, {
title: 'Second group',
children: [{ label: 'Mozzarella', value: 'mozzarella' },
{ label: 'Mushrooms', value: 'mushrooms' }]
}];
$("#example-post-checkboxName").multiselect('dataprovider', data);
$('.dropdown-menu').append(customOption);
//add actions on dynamically created button
$('.dropdown-menu').on("click", "#txtCategory", function (e) {
e.stopPropagation();
});
$('.dropdown-menu').on("click", "#btnAddOption", function () {
// alert('clicked');
var theValue = '<option>' + $('#txtCategory').val() + '</option>';
//$('#txtCategory').val();
$('#example-post-checkboxName').append(theValue);
$('#example-post-checkboxName').multiselect('rebuild')
{
$('.dropdown-menu').append(customOption);
alert('ok');
};
return false;
});
});
</script>
HTML
<div class="form-group">
<label class="col-sm-2 control-label">Multiselect</label>
<div class="col-sm-10">
<div id="theParentx">
<select id="example-post-checkboxName" name="multiselect[]" aria-labelledby="dropdownMenu3" multiple="multiple" required>
</select>
<div id="theChildx" class="dropdown-menu">
<input />
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default input-group-addon">Submit</button>
</div>
</div>
Add keydown event along with click to your dynamic textbox as below:
$('.dropdown-menu').on("keydown click", "#txtCategory", function (e) {
e.stopPropagation();
});
Updated Fiddle Here
I want select2 to behave as sort of combobox.See attached image for ref.
So if user types in a string but it is not found in source array, then on enter or closing select2 it should add that new string to source. So say if there were 2 values before, after above there would be now 3.
select2 just like combobox in file open dialogs
I have created sample code, but cant make it to work.I am unable to update source.
JSFIDDLE:
HTML:
<div class="row">
<div class="col-md-2">
<input type="hidden" id="select2_sample3" class="form-control ">
</div>
</div>
JS:
$(function () {
var preload_data = {
results: [{
id: 'user0',
text: 'Disabled User',
}, {
id: 'user1',
text: 'Jane Doe'
}]
};
$("#select2_sample3").select2({
placeholder: "Select...",
allowClear: true,
minimumInputLength: 1,
data: preload_data,
query: function (query) {
var data = {
results: []
}, i, j, s;
for (i = 1; i < 5; i++) {
s = "";
for (j = 0; j < i; j++) {
s = s + query.term;
}
data.results.push({
id: query.term + i,
text: s
});
}
query.callback(data);
}
}).on("select2-close", function () {
// add to
console.log("close");
});
});
I've recently had the same task. This is my solution:
<input type="hidden" name="trBrand" id="trBrand" class="form-control"></input>
and js code
$('#trBrand').select2({
placeholder: 'choose something',
allowClear: true,
id: function(object) {
return object.text;
},
createSearchChoice:function(term, data) {
if ( $(data).filter( function() {
return this.text.localeCompare(term)===0;
}).length===0) {
return {id:term, text:term};
}
},
data:preload_data
});