Search code examples
reactjstypescriptresponsivereact-grid-layout

Show two `react grid layout` dependently of each other


I want to have two react grid layout. One is on the left side and items are not changed their size. I can drag and drop them to the right side and then change their size or position. The dragged item should remove from the left side. I want to have a separator line between two parts. Please see the below picture so you can understand better. I've made a project and I could just show two layouts on the screen independently of each other. Now I want to make it dependently. I couldn't find a good example or tutorial. Thanks in advance

enter image description here


Solution

  • this one piece of code I made:

    import React, { useState } from "react";
    import GridLayout from "react-grid-layout";
    
    const initialLeftItems = [
      { id: "1", title: "Item 1", w: 2, h: 2 },
      { id: "2", title: "Item 2", w: 2, h: 2 },
      { id: "3", title: "Item 3", w: 2, h: 2 },
    ];
    
    const App = () => {
      const [leftItems, setLeftItems] = useState(initialLeftItems);
      const [rightItems, setRightItems] = useState([]);
    
      const handleDrag = (layout, oldItem, newItem) => {
        if (layout === "right") {
          setRightItems((prevItems) =>
            prevItems.map((item) =>
              item.id === newItem.i ? { ...item, x: newItem.x, y: newItem.y } : item
            )
          );
        } else {
          setLeftItems((prevItems) =>
            prevItems.filter((item) => item.id !== newItem.i)
          );
          setRightItems((prevItems) => [
            ...prevItems,
            { ...newItem, static: false },
          ]);
        }
      };
    
      return (
        <div>
          <GridLayout
            className="layout"
            layout={leftItems}
            cols={6}
            rowHeight={30}
            width={300}
            isDraggable={false}
            isResizable={false}
          >
            {leftItems.map((item) => (
              <div key={item.id} className="item">
                {item.title}
              </div>
            ))}
          </GridLayout>
          <div className="separator" />
          <GridLayout
            className="layout"
            layout={rightItems}
            cols={12}
            rowHeight={30}
            width={800}
            onDragStop={(layout, oldItem, newItem) => handleDrag("right", oldItem, newItem)}
            onResizeStop={(layout, oldItem, newItem) => handleDrag("right", oldItem, newItem)}
          >
            {rightItems.map((item) => (
              <div key={item.id} className="item" data-grid={item}>
                {item.title}
              </div>
            ))}
          </GridLayout>
        </div>
      );
    };
    
    export default App;
    

    In this example, I have two GridLayout components, one for the left side and one for the right side. The left side is not draggable or resizable, and the items are defined in the leftItems state. The right side is draggable and resizable, and the items are defined in the rightItems state.

    When an item is dragged from the left side to the right side, I remove it from the leftItems state and add it to the rightItems state. I also set the static property of the item to false so that it can be dragged and resized on the right side.

    The handleDrag function is called whenever an item is dragged or resized on the right side. It updates the rightItems state with the new position and size of the item.

    Lastly, I have a separator line between the two GridLayout components to visually separate them.

    Hope this helps!