-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Synchronize TableWidget row selection #1067
Synchronize TableWidget row selection #1067
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #1067 +/- ##
=======================================
Coverage 67.85% 67.85%
=======================================
Files 112 112
Lines 6679 6679
=======================================
Hits 4532 4532
Misses 2147 2147
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
let domElement = document.createElement("div"); | ||
el.classList.add("custom-table"); | ||
let selectedIndices = []; | ||
|
||
function drawTable() { | ||
const data = model.get("data"); | ||
domElement.innerHTML = ""; | ||
let innerHTML = '<table><tr>' + data[0].map(header => `<th>${header}</th>`).join('') + '</tr>'; | ||
|
||
for (let i = 1; i < data.length; i++) { | ||
innerHTML += '<tr>' + data[i].map(cell => `<td>${cell}</td>`).join('') + '</tr>'; | ||
} | ||
|
||
innerHTML += "</table>"; | ||
domElement.innerHTML = innerHTML; | ||
|
||
const rows = domElement.querySelectorAll('tr'); | ||
rows.forEach((row, index) => { | ||
if (index > 0) { | ||
row.addEventListener('click', () => { | ||
const rowIndex = index - 1; | ||
if (selectedIndices.includes(rowIndex)) { | ||
selectedIndices = selectedIndices.filter(i => i !== rowIndex); | ||
row.classList.remove('selected-row'); | ||
} else { | ||
selectedIndices.push(rowIndex); | ||
row.classList.add('selected-row'); | ||
} | ||
model.set('selected_rows', [...selectedIndices]); | ||
model.save_changes(); | ||
}); | ||
|
||
row.addEventListener('mouseover', () => { | ||
if (!row.classList.contains('selected-row')) { | ||
row.classList.add('hover-row'); | ||
} | ||
}); | ||
|
||
row.addEventListener('mouseout', () => { | ||
row.classList.remove('hover-row'); | ||
}); | ||
} | ||
}); | ||
} | ||
|
||
function updateSelection() { | ||
const newSelection = model.get("selected_rows"); | ||
selectedIndices = [...newSelection]; // Synchronize the JavaScript state with the Python state | ||
const rows = domElement.querySelectorAll('tr'); | ||
rows.forEach((row, index) => { | ||
if (index > 0) { | ||
if (selectedIndices.includes(index - 1)) { | ||
row.classList.add('selected-row'); | ||
} else { | ||
row.classList.remove('selected-row'); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
drawTable(); | ||
model.on("change:data", drawTable); | ||
model.on("change:selected_rows", updateSelection); | ||
el.appendChild(domElement); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand, why is it marking the entire code as a change? I can't tell what you changed 🤷🏻♂️ That said, from the behavior in the clip, seems like you solved it. But maybe you can say a bit what happened?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i was doing a test in a jupyter notebook , then i guess in the copy paste it moves the spaces , so the issue is that I added
function updateSelection() {
const newSelection = model.get("selected_rows");
selectedIndices = [...newSelection];
const rows = domElement.querySelectorAll('tr');
rows.forEach((row, index) => {
if (index > 0) {
if (selectedIndices.includes(index - 1)) {
row.classList.add('selected-row');
} else {
row.classList.remove('selected-row');
}
}
});
}
So when i assigned selected_row in python it is reflected in the JS, because before the selection was keeping the previous state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and to listen this changes i added , so is i set to selected_rows in Python it will triggers the function updateSelection
model.on("change:selected_rows", updateSelection);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't tell what changed 🤷🏻♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Hi @AndresOrtegaGuerrero and @edan-bainglass , for the @AndresOrtegaGuerrero, please have a look to see if it can also be used here. |
Very nice! Performance okay? |
React, and Datagrid libraries are used, making it smooth, even for large data. |
This PR addresses the issue of inconsistent row selection states in the table , in particular when the widget clear a selection in the table , but if you click the table it might retain extra information of the selection.
An updateSelection function is included to synchronize the selectedIndices array in JavaScript with the selected_rows list from Python
Old
Screen.Recording.2025-01-08.at.16.07.44.mov
New
Screen.Recording.2025-01-08.at.16.05.38.mov