Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ag-grid menu in a sticky column

Is there any way to add a menu for each row in a sticky column (in Ag-grid)?

There is no mention about such feature in the official docu, so I'm not sure whether it's even possible. I have tried couple of ways but the menu is always trapped inside the sticky column wrapper.

The only way I could make it (at least) partially working, was by setting:

.ag-body-container .ag-row {
        z-index: 0;
    }

    .ag-ltr .ag-hacked-scroll .ag-pinned-right-cols-viewport {
        overflow: visible !important;
    }

but that completely ruined vertical scrolling.

var columnDefs = [
    {headerName: "ID", width: 50,
        valueGetter: 'node.id',
        cellRenderer: 'loadingRenderer'
    },
    {headerName: "Athlete", field: "athlete", width: 150},
    {headerName: "Age", field: "age", width: 90},
    {headerName: "Country", field: "country", width: 120},
    {headerName: "Year", field: "year", width: 90},
    {headerName: "Date", field: "date", width: 110},
    {headerName: "Sport", field: "sport", width: 210},
    {headerName: "Gold", field: "gold", width: 300},
    {headerName: "Silver", field: "silver", width: 400},
    {headerName: "Bronze", field: "bronze", width: 200},
    {headerName: "Menu", field: "", width: 100, pinned: 'right', cellRenderer: 'menuRenderer' }
  ];
  
  function MenuRenderer( params ) {
  }	

	MenuRenderer.prototype.init = function(params) {
		this.eGui = document.createElement('div');
		this.eGui.classList.add('menu');
		var menuElement = `
			<a href="#">  * </a> 
			<div class="menu--list"> 
			</div>
		`;
		this.eGui.innerHTML = menuElement;
	};

	MenuRenderer.prototype.getGui = function() {
		return this.eGui;
	};


  var gridOptions = {
    components:{
        loadingRenderer: function(params) {
            if (params.value !== undefined) {
                return params.value;
            } else {
                return '<img src="./loading.gif">'
            }
        },
		'menuRenderer': MenuRenderer

    },
    columnDefs: columnDefs,
	rowBuffer: 0,
	rowModelType: 'infinite',
	paginationPageSize: 100,
	cacheOverflowSize: 2,
	maxConcurrentDatasourceRequests: 2,
	infiniteInitialRowCount: 0,
	maxBlocksInCache: 2,
	//embedFullWidthRows:true, 
    onGridReady: function (params) {
      params.api.sizeColumnsToFit();
    }
  }

  // wait for the document to be loaded, otherwise,
  // ag-Grid will not find the div in the document.

  document.addEventListener("DOMContentLoaded", function() {
    // lookup the container we want the Grid to use
    var eGridDiv = document.querySelector('#myGrid');

    // create the grid passing in the div to use together with the columns & data we want to use
    new agGrid.Grid(eGridDiv, gridOptions);
	
	 agGrid.simpleHttpRequest({url: 'https://raw.githubusercontent.com/ag-grid/ag-grid-docs/master/src/olympicWinners.json'}).then(function(data) {
        var dataSource = {
            rowCount: null, // behave as infinite scroll
            getRows: function (params) {
                console.log('asking for ' + params.startRow + ' to ' + params.endRow);
                // At this point in your code, you would call the server, using $http if in AngularJS 1.x.
                // To make the demo look real, wait for 500ms before returning
                setTimeout( function() {
                    // take a slice of the total rows
                    var rowsThisPage = data.slice(params.startRow, params.endRow);
                    // if on or after the last page, work out the last row.
                    var lastRow = -1;
                    if (data.length <= params.endRow) {
                        lastRow = data.length;
                    }
                    // call the success callback
                    params.successCallback(rowsThisPage, lastRow);
                }, 500);
            }
        };

        gridOptions.api.setDatasource(dataSource);
    });
  });
/* Menu */
	.menu {
		z-index: 2 !important;
		position: fixed;
		top: 20%;
		left: 50%;
	}
	
	.menu a {
		text-decoration: none;
	}
	
	.menu .menu--list {
		display: none;
		position: absolute;
		top: 0;
		right: 0px;
		width: 100px;
		height: 50px;
		border: 1px solid red;
	}
	
	.ag-body-container .ag-row {
		z-index: 0;
	}

	.ag-ltr .ag-hacked-scroll .ag-pinned-right-cols-viewport {
		overflow: visible !important;
	}
	
	.ag-pinned-right-cols-viewport .ag-row:first-child .menu--list{
		display: block;
	}

	/* [Layout] */
  .fill-height-or-more {
    min-height: 100%;
    display: flex;
    flex-direction: column;
    border: 1px solid red;
  }
  .fill-height-or-more > div {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  .some-area > div {
    padding: 1rem;
  }
  .some-area > div:nth-child(1) {
    flex-grow:0;
    background: #88cc66;
  }
  .some-area > div:nth-child(2) {
    flex-grow: 0;
    background: #ec971f;
  }
  .some-area > div:nth-child(3) {
    position: relative;
    padding: 0;
    justify-content: stretch;
    align-content: flex-start;;
    flex-grow:1;
    background: #8cbfd9;
  }
  .some-area > div:nth-child(4) {
    flex-grow: 0;
	position: absolute;
    background: #ec971f;
  }
  .some-area > div h2 {
    margin: 0 0 0.2rem 0;
  }
  .some-area > div p {
    margin: 0;
  }
  .inner{ position: absolute; top: 0; bottom: 0; left: 0; right: 0; }

  html, body {
    padding:0;
	margin: 0;
    height: 100%;
	overflow: hidden;
  }
  
  .ag-body-viewport {
	-webkit-overflow-scrolling: touch;
	}
<head>
  <script src="https://unpkg.com/ag-grid/dist/ag-grid.min.js"></script>
</head>

<html>
  <body>
  <section class="some-area fill-height-or-more">
    <div>
      Header
    </div>
    <div>
      Action bar
    </div>
    <div>
      <div class="inner">
        <div id="myGrid" style="height: 100%; width:100%; font-size: 1.4rem" class="ag-theme-fresh"></div>
      </div>
    </div>
  </section>
  </body> 	
</html>
like image 763
Alexus Avatar asked May 20 '18 16:05

Alexus


People also ask

How do I hide the column menu in Ag grid?

To not show the menu at all, set this property to an empty array [] . In addition, you can set the attribute suppressMenu=true to the column definition to not show the menu for a particular column. The order of the menu tabs shown in the menu will match the order you specify in this array.

How do you freeze rows on Ag grid?

To put pinned rows into your grid, set pinnedTopRowData or pinnedBottomRowData in the same way as you would set normal data into rowData . After the grid is created, you can update the pinned rows by calling api. setPinnedTopRowData(rows) and setPinnedBottomRowData(rows) .

How do I add a tooltip to Ag grid column?

When we want to display a header tooltip, we set the headerTooltip config as a string , and that string will be displayed as the tooltip. However, when working with custom tooltips we set colDef. tooltipComponent to assign the column's tooltip component and the headerTooltip value will passed to the params object.

What is column pinning?

Pinned (or frozen, locked, or sticky) columns are columns that are visible at all time while the user scrolls the grid horizontally. They can be pinned either to the left or right side and cannot be reordered.


1 Answers

I would completely abandon the idea of adding the menu inside the cell.

What I would do instead is:

  • Add the menu outside the grid, hidden,
  • Keep the link in the cell (this would trigger the menu later)
  • Add click event to this link
  • Create a class for the menu (can be global, as there will be only one menu, with changing context)
    • This would hide/show the menu
    • Have parameters, which store the context (data from your grid, or whatever)
  • The click event on the links from the grid would have code which shows the menu

Something like this: This example has no error handling for brevity.

var gridMenu = function(selector) {
    var instance = this;
    instance.element = document.querySelector(selector);
    instance.context = null; // this can be any data, depends on your project

    // sender is the link from your cell
    // context is your data (see above)
    instance.open = function(sender, context) {
        instance.context = context;
        // you may even add the sender element to your context

        instance.element.style.display('block');
        // alternatively, you could use instance.element.classList.add('some_class_to_make_menu_visible')
        // you may need to add some positioning code here (sender would contain valuable data for that)
    }

    instance.close = function () {
        instance.context = null;
        instance.element.style.display = 'none';
        // or you may remove visibility class
    }

    // click events for menu items (if you use some Javascript processing, and the menu doesn't use simple links)
    instance.menuItem1Click = function(e) {
         // do whatever you wish here
         instance.close();
         // call this at the end of each of your menu item click event handlers
    }

    // ... more click event handlers for your other menu items (one for each menu item)

    return instance;
}

// Create your menu item somewhere in your document ready code, or even where you initiate your grid (before initializing the grid)
var menu = new gridMenu("#my_awesome_floating_menu");

This is a sample click event of your links inside the grid:

function cellLinkClick(event) {
    var context = {}; // whatever data you may want to send to the menu
    menu.open(event, context);
}
like image 76
beerwin Avatar answered Oct 07 '22 13:10

beerwin