Our blazing fast Grid component built with pure JavaScript


Post by saurabhdesai »

Hi team,

we are using a tree grouping grid. In which we are trying to assign different renderers for every header in the same column. For example, suppose we grouped the grid by two columns col1 and col2

grouped Column definition:

{
	field:'xyz',
	renderer:'groupRenderer',
	items:[
			{
				field:'col1'
				renderer:'renderer1'
			},
			{
				field:'col2'
				renderer:'renderer2'
			}
		]
}

Files:
GroupRenderer.js //based on record object keys this component maps Renderers object from renderers.js
renderers.js //This is an object which contains all the possible renderers in key-value pair
Below is the content of renderers.js

{
renderer1:(props)=>{
	return <renderer1. {...props}/>
}
renderer1:(props)=>{
	return <renderer1  {...props}/>
}
grouprenderer:(props)=>{
	return <GroupRenderer {...props}/>
}
}

renderer1.js //renderer for header1
renderer2.js //renderer for header2

So when the grid loads initially we are mapping the renderer from renderers.js with the help of the renderer property which is defined in a column definition. Then in gropupRenderer.js, we are accessing the renderer name of that cell from the items array of a column definition, and then corresponding to the renderer name we are calling the defined component. Also we are sending updated data to the renderer component. But the issue we are facing is initially values are getting rendered correctly but as some editing happens in the cell GroupRenderer is not getting called again only the renderer specific to the cell is getting called again(for ex. if editing happens in cell1 then directly renderer1 is getting called without going through grouprenderer. Because of this renderer1 not getting updated value. Can you please help me with this problem?


Post by alex.l »

Hi saurabhdesai,

Why don't put all the logic about renderer in the column renderer method itself and decide how it should be displayed using record and other properties available in https://bryntum.com/docs/grid/api/Grid/column/Column#config-renderer
I can't answer why groupRenderer has not been called. Maybe it shouldn't at all, because it will be called only if cell value needs to be updated. I also don't know if you will have correct order of call in that case. And I didn't get where exactly you placed all these methods. I need more context.
Best of all put all required logic into renderer method of entire column and do all checks inside.
I can't get more specific recommendation without a test case. So if you share a runnable test case, it will allow us to give you fast and good answer.

All the best,
Alex


Post by saurabhdesai »

Hi team,

Below is our order of call.
GroupRenderer.js

	import renderers from 'renderer.js'
	const rendererName=items.map(()=>{})   //rendererName=renderer1
	const renderer=renderers[rendererName]  
record.set(field,value) //updating record here return( <> renderer(updatedRecord) // assigning renderer1 with updated props </>)

Renderer1.js

 

 
 
const handleClick =()=>
{
	const data=fetch() //async call
	setData(data)
}
return(
<>
{props.updatedRecord.value}
<button onclick={handleClick}></button>
<Menu>
{data}
</Menu>
</>)

 //on click this renderer is getting called directly which leads to not getting updatedRecord
 

firstly groupRenderer is getting called. In groupRenderer.js we are updating one of the properties of the record and then passing that updated record to the renderer1 In that particular renderer, we are giving one button. with the click of a button, we are fetching some data from the server and showing it as a dropdown on the button. But when clicking on that button, the renderer1 gets called without going through groupRenderer.As groupRenderer is not getting called renderer1 is not getting correct values.


Post by mats »

You should not mutate records inside renderer code:

	record.set(field,value) //updating record here 

Post by saurabhdesai »

Hi team,
Sorry, there is a typo mistake. I want to update the column field in the group renderer. So that we can send the updated props to the corresponding renderer. And based on that field name we are rendering values in the cell and also we are making an async server call with the click of a button from the corresponding renderer to show a dropdown value. But as soon as we click on the button to get dropdown values only the corresponding renderer is getting called without going through groupRenderer which results in not getting the correct column field name. Because of that cell value becomes empty.
Can you please guide me on this issue.


Post by alex.l »

Yes, we can guide you, but that still not clear to us what exactly you did. As I said, renderer will be called ONLY in case cell value should be updated (has changes), and it's not guaranteed that groupRenderer will be called before child cell. We also mentioned that you cannot modify record inside a renderer.
I still don't have a full picture, my I guess we need to find a better approach to reach your goals.
Please post a runnable test case with comments what you expecting, it will allow us to help you fast.

All the best,
Alex


Post by saurabhdesai »

Hi team,

PFA runnable test case. In the attached test case, as soon as we click on three dot menus that come on the hover of a parent element, A cell becomes empty. Ideally, onClick of three dot menus 3 options should come up as shown in the attached screenshot.

Thanks and Regards,
Saurabh Desai

Attachments
Screen Recording 2022-11-14 at 4.58.53 PM.mov
(1.02 MiB) Downloaded 39 times
grid_Bryntum_demo.zip
(432.5 KiB) Downloaded 43 times
Ideal_Behaviour.png
Ideal_Behaviour.png (12.74 KiB) Viewed 642 times

Post by alex.l »

I am not sure that's the problem of renderer, but components (or the way) you used.
I don't know how to use Ant library and dropdown, etc.
I just copied from the Ant website here https://ant.design/components/dropdown/ some code and replaced yours a bit


  const menu = (
    <Menu>
      <Menu.Item>item 1</Menu.Item>
      <Menu.Item>item 2</Menu.Item>
    </Menu>
  );

  return (
    <div>
      <div style={{ padding: "2px" }}>
        <a href="#">
          {value.hasOwnProperty("text") ? value.text : value}
          &nbsp;
        </a>

    {value && (

        <Dropdown overlay={menu}>
          <a>Hover me</a>
        </Dropdown>

    )}
  </div>
</div>
  );
};

It works and I see menu. Of course, I see "deprecated" errors in console, but this test shows me the problem in component you used or the way you defined it. I can't suggest you how to use Ant dropdown because I don't know Ant and don't understand the syntax. Try to play with this code and let us know if any luck.

There is a workaround: just use our components and menus which work great.
https://bryntum.com/docs/grid/api/Core/widget/Menu
https://bryntum.com/docs/grid/api/Core/widget/Button
https://bryntum.com/docs/grid/api/Grid/column/WidgetColumn

All the best,
Alex


Post Reply