Search code examples
react-grid-layout

How to implement static sized grid like 3x3 in React-Grid-Layout


I want to have a grid which will always have for example 3 rows and 3 columns. Now suppose these are my grid items

      <div className="myClass" key="1">1</div>
      <div className="myClass" key="2">2</div>
      <div className="myClass" key="3">3</div>
      <div className="myClass" key="4">4</div>
      <div className="myClass" key="5">5</div>
      <div className="myClass" key="6">6</div>
      <div className="myClass" key="7">7</div>
      <div className="myClass" key="8">8</div>
      <div className="myClass" key="9">9</div>

suppose all items have same width and height and are not resizable.

If I drag 9 over to 6 aka vertically the items will just swap their places. However if I drag 9 over to 8 aka horizontally the 8 item will go down to a new row and 9 will be in place of 8 while the previous place of 9 will be empty. Is it possible to make items just swap places during horizontal drag as well, instead of creating a new row?


Solution

  • So I added the onLayoutChange to the ReactGridLayout

    Read code comments for more details.

    private onLayoutChange = (layout: any) => {
        const fixedLayout = this.fixLayout(layout)
        this.setState({
          layout: fixedLayout
        })
      }
    
      /**
       * The `react-grid-layout` lib is not swapping items during horizontal dragover
       * Rather it moves the items into a new row
       * Since we need a static 3x3 row, let's fix that
       */
      private fixLayout = (layout: any) => {
        // `y` is calculated by `h` in the layout object, since `h` is 20
        // first row will be 0, second 20, third 40
        const maxY = 40
    
        // when an item goes to a new row, there is an empty column in the maxY row
        // so here we find which columns exist
        // tslint:disable-next-line:max-line-length
        const maxRowXs = layout.map((item: any) => item.y === maxY ? item.x : null).filter((value: any) => value !== null)
    
        // xs or cols, we only have 3 cols
        const xs = [0,1,2]
    
        // find the missing col
        // tslint:disable-next-line:max-line-length
        const missingX = xs.find((value: any) => maxRowXs.every((maxRowX: number) => maxRowX !== value))
    
        // bring the item from the new row into maxY row
        // and place it in the missing column
        const fixedLayout = layout.map((item: any) => {
          if (item.y > maxY) {
            return {
              ...item,
              y: maxY,
              x: missingX
            }
          }
          return item
        })
        return fixedLayout
      }