I'm using the React Grid component and I'm looking for a way to fire a function when double click a row.
I found a rowClick function and I can use it now to select a row or handle an onClick event : <Grid rowClick={e => yourFunction(e)}> .
But there is no function to handle a doubleClick event.
This is my approach, I passed a onDoubleClick() function as props to my component, and bind it with the listener of doubleClick on componentDidMount for each row :
componentDidMount() {
let { onDoubleClick } = this.props;
if (onDoubleClick) {
const rows = document
.getElementsByClassName('k-widget k-grid')[0]
.getElementsByClassName('k-grid-table')[0]
.getElementsByTagName('tbody')[0]
.getElementsByTagName('tr');
for (let i = 0; i < rows.length; i++) {
rows[i].addEventListener('dblclick', () => onDoubleClick());
}
}
}
For the moment this works but I'm not able to pass the clicked row data to my function.
Is there any hack to retrieve the row's data using the element ?
Like this for example : onDoubleClick(kendo.data.DataSource(rows[i])) => return the json data to function.
The grid have a rowRender property, that can be used as a RenderProp for fully modifying the rows, including attaching them a rowClick using the native React approach.
rowRender(trElement, dataItem) {
const trProps = {
...trElement.props,
onDoubleClick: () => {
//place your logic here
}
};
return React.cloneElement(trElement, { ...trProps }, trElement.props.children);
}
You may find this live example for how to attach mouse mousedown, blur and focus for the GridRow in the InCell editing demo The same logic for the onDoubleClick can be used as in my code-snipped above.
Related
folks!
Does anyone know the opposite method to cellFocused in ag-grid?
I need to detect when the focused cell loses its focus and run some actions.
Thanks for your responses.
I've found a way to support onBlur event. Since ag-grid doesn't have a built-in method, I created wy own event listener to the focus cell node and remove it after losing the focus state.
So, my code looks like this. Inside the react class I have 3 additional methods:
removeCellBlurListener = () => {
const target = document.activeElement;
if (target) {
target.removeEventListener('blur', this.onCellBlur);
}
};
addCellBlurListener = () => {
const target = document.activeElement;
if (target) {
target.addEventListener('blur', this.onCellBlur);
}
};
onCellBlur = () => {
...do something on blur
};
render () {
return (
<AgGridReact
{...restProps}
onCellFocused={(e) => this.addCellBlurListener()}
onGridReady={this.onGridReady}
/>
);
}
I've faced with problem using React and React Material-UI components. What I need:
1) User clicks button in my component - I should add mousemove listener to the page and show ProgressBar.
2) User moves mouse - I count events, and update my ProgressBar.
3) When count of events is 50, I remove mousemove listener and hide ProgressBar.
I tried to do this with React useEffect, useState Hooks, but it does not remove listener. I don't understand, why.
Here is my code:
const [completed, setCompleted] = React.useState(0);
const [keyGenState, setKeyGenState] = React.useState(0);
const updateMousePosition = ev => {
console.log("UMP");
setCompleted(old => old + 1);
/*I tried to check completed value here, but it always is 0 - maybe, React re-renders component on setState..
And I decided to take useEffect hook (see below)*/
};
useEffect(() => {
console.log(completed); /*Just to understand, what happens) */
if (completed === 49) {
return () => {
/*When completed value is 50, this log message appears, but mouse listener still works! */
console.log("Finish!");
document.removeEventListener("mousemove", updateMousePosition);
setKeyGenState(2);
}
}
}, [completed]);
function handleChange(e) {
switch (e.currentTarget.id) {
/*startKeyGen - it is ID of my Button. When user clicks it, I show ProgressBar and add mousemove listener*/
case "startKeyGen" : {
setKeyGenState(1);
document.addEventListener("mousemove", updateMousePosition);
break;}
}
}
/*Other logics. And finally, JSX code for my ProgressBar from Material-UI*/
<LinearProgress hidden={keyGenState !== 1 } variant="determinate" value={completed} style={{marginTop: 10}} />
It looks really strange: why React ignores removeEventListener.
Please, explain, where is my mistake.
UPD: Thanks a lot! I used useCallback hook, in this manner:
const updateMousePosition = React.useCallback(
(ev) => {
//console.log("Calback");
console.log(ev.clientX);
setCompleted(old => old + 1);
},
[],
);
useEffect(() => {
//console.log(completed); /*Just to understand, what happens) */
if (completed === 49) {
return () => {
/*When completed value is 50, this log message appears, but mouse listener still works! */
console.log("Finish!");
document.removeEventListener("mousemove", updateMousePosition);
setKeyGenState(2);
}
}
});
But I still don't understand completely.. So, when I used useCallback with empty dependencies array, this function (updateMousePosition), will be unchanged during all "life" of my component? And in useEffect I remove mouseListener. It is magic for me: why does useEffect ignore removing without useCallback?
Try to use React.useCallback for updateMousePosition. Every change in your component creates new function (reference). So React.useEffect remove last updateMousePosition but doesn't remove added in handleChange.
I am dynamically creating a table where i am adding onclick function to each column.
for (var x = 0; x < r.length; x++) {
//Setting the columns
if (i === 1) {
var headerCell = document.createElement("TH");
headerCell.innerHTML = r[x];
headerCell.id = x;
headerCell.onclick = function () {
sortTable(this.id, name);
}
row.appendChild(headerCell);
}
}
In a specific situation I want to disable the onclick function. Here is the code and it works.
$('#errorTable TH').prop("onclick", null).off("click");
and in another situation i want to reattach the onclick function. And that doesn't work. I want to enable the original function....
Any ideas ?
The way you created your table and adding/removing events are not easily maintainable. I also have some suggestions:
Review your code and define code click handler separately.
If you use jQuery in your project use it every where, if not, do not use it anywhere.
In your code i is undefined.
Add Remove Event Listener with jQuery
First define your handler function:
var myClickHandler = function(){
// this is your click handler
alert('Yes!!!');
}
Select your element and assign to a variable. <div id="clickable">Click Me!</div> must be in the DOM at the time of below script executed.
var element = $('#clickable');
// assign event listener
element.on('click',myClickHandler);
// remove event listener:
element.off('click',myClickHandler);
note that you must have to inform jQuery which handler should be removed.
See a sample https://codepen.io/softberry/pen/BEpove
An alternative is to build a click handler that checks a "kill switch".
var tableClickable = true;
headerCell.onclick = function () {
if (tableClickable) {
sortTable(this.id, name);
}
}
//In a specific situation I want to disable the onclick function.
something.addEventListener('someEvent', function () {
tableClickable = false;
});
//and in another situation i want to reattach the onclick function.
something.addEventListener('someOtherEvent', function () {
tableClickable = true;
});
This answer shows how to hide visible elements. I want to create action for switching visibilities some elements. According to documentation I need to use element.removeAttr to remove some attributes. I can see removed ./display', 'none' attribute, but on UI elements are still hidden - they should be visible.
Do you know what I'm missing? Should I rerender UI somehow?
Below is my event.
paper.on('cell:pointerdown', function switchTaskVisibility(...args) {
const selectedItem = args[0];
const successors = graph.getSuccessors(selectedItem.model);
const tasks = successors.filter(function isElementOfTypeTask(element) {
const type = element.prop('type');
if (type === 'task') return element;
});
console.log(tasks);
const hasVisibleTasks = selectedItem.model.prop('hasVisibleTasks');
if (hasVisibleTasks) {
tasks.forEach((element) => {
element.attr('./display', 'none');
});
}
else {
tasks.forEach((element) => {
element.removeAttr('./display');
});
}
// HERE I CAN SEE THAT DISPLAY ATTRIBUTE SWITCHES CORRECTLY
// BUT AFTER FIRST HIDING OF ELEMENTS I CANNOT MAKE THEM VISIBLE IN UI
console.log(graph.getSuccessors(selectedItem.model));
selectedItem.model.prop('hasVisibleTasks', !hasVisibleTasks);
});
Thanks,
Rafal
I found some workaround. From some reason removeAttr doesn't rerender elements properly, so I tested visibility property like this:
const hasVisibleTasks = selectedElement.prop('hasVisibleTasks');
if (hasVisibleTasks) {
cells.forEach((element) => {
element.attr('./visibility', 'hidden');
});
}
else {
cells.forEach((element) => {
element.attr('./visibility', 'visible');
});
And works fine. But I still don't understand why element.removeAttr('./display') didn't rerender UI earlier.
Best regards,
Rafal
Irrespective of the solution, Why you are using const data type for hasVisibleTasks as it seems the value of this variable is changing in run-time.
i'm working with slickgrid and i'm quit new in slickgrid. i want to know is there any function through which i can get the complete info of all the cell to a specific row where user will click ??? also i want to get values before and after editing in the specific cell so that i can measure the change in the cell.
for getting the active cell (i.e. where user clicked) i'm using
ifkaar_scenarioConfigTable.onClick.subscribe(cellClicked);
and i'm checking where the cell is my desired cell(i.e. where user is allowed to do editing/modification) as following
function cellClicked(e) {
var cell = ifkaar_scenarioConfigTable.getCellFromEvent(e);
if (col[cell.cell].id == "orderqty") {
console.log("orderqty pressed");
}
}
this is working fine , i.e. when i click on any cell , it tell whether it is "orderqty" or not , but further i want to get its value and other cells' value in order to calculate the changes. I've searched but couldn't find any clear article (or i can't understood properly). any help will be highly appreciated. Thanks
the onClick event passes the row as an argument
Get the data item for a clicked row
function cellClicked(e, args) {
var item = grid.getDataItem(args.row);
}
Check if a click happened in a specific column
function cellClicked(e, args) {
if (args.cell == grid.getColumnIndex('orderqty')) {
console.log("orderqty pressed");
}
}
You could even pull this filtering functionality out into its own function and pass a callback when a click happens in that column
function forColumn(row, cell, columnID, fn) {
var cellNode = grid.getCellNode(row, cell);
var dataContext = grid.getDataItem(row);
if (cellNode && grid.getColumns()[cell].id === columnID) {
fn.call(this, cellNode, dataContext, row, cell);
}
}
function cellClicked(e, args) {
forColumn(args.row, args.cell, 'orderqty', function (cellNode, dataContext, row, cell) {
console.log("orderqty pressed");
});
}
Values before and after edit
To get the values of a cell before and after an edit you will need to handle this in the isValueChanged function in the editor for a column.
function cellClicked(e) {
var grid = ifkaar_scenarioConfigTable;
var cell = grid.getCellFromEvent(e);
var item = grid.getDataItem(cell.row); // all the data in the row
if (cell.cell == grid.getColumnIndex('orderqty')) {
console.log("orderqty pressed");
}
}
If you access grid from other control like . click button
var selectRow = gridInstance.getSelectedRows();
alert(gridInstance.getDataItem(selectRow).columnName)