itables
itables copied to clipboard
Row selection?
I'm using itables in a Shiny app and I was wondering if there's a way I can implement row selection?
Oh I found this in the documentation: https://mwouts.github.io/itables/advanced_parameters.html#select-rows
So it's not currently supported? Any way I could implement it myself?
Thanks for looking into this! Do you think you could add the extension to the connected template https://github.com/mwouts/itables/blob/main/itables/html/datatables_template_connected.html ? That would be a great start !
Sorry I actually don't have the bandwidth to do a full PR, but I can document a hacky workaround I was able to figure out.
I manually added the select extension js/css files and then I inject my own document.ready code into my webpage
app_ui = ui.page_fluid(
ui.head_content(
ui.tags.link(rel="stylesheet", type="text/css", href="https://cdn.datatables.net/buttons/2.4.2/css/buttons.dataTables.min.css"),
ui.tags.script(src="https://cdn.datatables.net/1.10.24/js/jquery.dataTables.min.js"),
ui.tags.link(rel="stylesheet", type="text/css", href="https://cdn.datatables.net/select/1.7.0/css/select.dataTables.min.css"),
ui.tags.script(src="https://cdn.datatables.net/select/1.7.0/js/dataTables.select.min.js")
# custom js to send the selected row data to Shiny server
ui.HTML("""
<script>
const attachSelectHandler = function() {
setTimeout(function() { //hack to wait for the table to initialized
dt = $('table').DataTable();
dt.on('select', function (e, dt, type, indexes) {
if (type === 'row' && indexes.length > 0) {
// Send the selected row data to Shiny server
var index = indexes.pop();
console.log('selected index', index);
Shiny.setInputValue('selectedRow', index);
}
});
},2000);
};
$(document).ready(function () {
attachSelectHandler();
Shiny.addCustomMessageHandler("clearSelection", function(message) {
console.log('clearSelection');
Shiny.setInputValue('selectedRow', 0);
attachSelectHandler();
});
});
</script>
""")
...
)
Then in my server code I can make sure to initialized DT with select=True
def server(input, output, session):
async def clear_selection(): #this can be called to clear the selection from the server
await session.send_custom_message(type="clearSelection", message=None)
@render.ui
def ouput_df():
df = get_df()
dt_html = DT(df, select=True)
return ui.HTML(dt_html)
I'll leave it to you if you want to keep the issue open!
Thanks! Yes, please leave the issue open. Thanks for the Shiny code, I am sure it will be helpful to others until we can support extensions in itables!
Row selection is now supported (well, included in the default bundle) in itables==2.0. @michael-erasmus do you think you could update your example above? Thanks!
Thank you for the great tool. I also see the select row is now available, but how can I get the selected row id? what is the input element I can use from Shiny?
Thanks @maxmoro . Well while the select extension is bundled within ITables, so rows can be selected, at the moment it's not possible yet to get this information back in Python (the code above was for an earlier version of ITables). I'll update this issue when I find out how to do this.
Thank you @mwouts for the prompt reply. I perfectly understand. I was able to adapt the code above to get the row_id. I'm good for the moment, and I'm happy to test the updated select version as soon is out.
Oh great! Can you share back how you do it? Thanks!
Unfortunately my code it is not fully working, I didn't notice I was reloading the jquery library twice. (so multiple tables have been created) I'm now stuck at the error DataTable is not a function (I'm very new to JS) This is my snippet of the attachSelectHandler code
const attachSelectHandler = function() {
console.log('p1')
setTimeout(function() { //hack to wait for the table to initialized
var tables = $('.dataTable')
console.log('p2')
console.log(tables)
tables.each(function() {
var table = $(this).DataTable();
console.log('c')
// console.log(table)
table.on('select', function (e, dt, type, indexes) {
if (type === 'row' && indexes.length > 0) {
// console.log('d')
tableId = dt.table().node().id
// Send the selected row data to Shiny server
var index = indexes.pop();
// console.log(tableId)
console.log('selected index', index);
Shiny.setInputValue(`${tableId}_selectedRow`, index);
};
});
});
},2000);
};
Looking at the web, looks like the right library is not loaded. or we need a defer on jquery.dataTable.mins.js link
Or, do you have any insight?
Hey @michael-erasmus , I am finally coming back to this topic!
In the PR #319 I have been able to do the following
- Provide a Jupyter widget for ITables
- Make DT work offline in a Shiny app (this is the call to
init_shiny_modeat https://github.com/mwouts/itables/blob/try_anywidget/tests/sample_python_apps/itables_in_a_shiny_app.py) - Create and update a shiny input
{table_id}_selected_rowswhen an explicittable_idis passed
There is one thing that I have not been able to do yet, that is to update the row selection using e.g.
session.send_custom_message("countries_select_rows", {"selected_rows":[0,1]})
Is that something that you are still interested in? I tried to add the following to selected_row_code:
Shiny.addCustomMessageHandler("{table_id}_select_rows", function(message) {{
DataTable.set_selected_rows(dt, filtered_row_count, message.selected_rows);
}});
but that was not enough. Do you think we need to solve that? Note that passing selected_rows as an argument to DT already works in that PR.
I'll close this issue as DT now has selected_rows argument in ITables v2.2 (see this example).
Feel free to open another one re updating the row selection using a custom message!
Actually using the ITable widget seems way easier! I have updated the documentation accordingly. Let me know what you think. Thanks