Hands-on with AG Grid's React Data Grid
From Author:
Get started with AG Grid React Data Grid with a hands-on tutorial from the core team that will take you through the steps of creating your first grid, including how to configure the grid with simple properties and custom components. AG Grid community edition is completely free to use in commercial applications, so you'll learn a powerful tool that you can immediately add to your projects. You'll also discover how to load data into the grid and different ways to add custom rendering to the grid. By the end of the workshop, you will have created an AG Grid React Data Grid and customized with functional React components.
- Getting started and installing AG Grid
- Configuring sorting, filtering, pagination
- Loading data into the grid
- The grid API
- Using hooks and functional components with AG Grid
- Capabilities of the free community edition of AG Grid
- Customizing the grid with React Components
This workshop has been presented at React Summit 2022, check out the latest edition of this React Conference.
FAQ
In React, `useImperativeHandle` is used to expose functions from a child component to a parent component when using refs. This is particularly useful in custom functional components to expose specific functionalities like methods, which are necessary for lifecycle operations in AG Grid custom filters, such as `isFilterActive` and `doesFilterPass`.
To save and restore filter states in AG Grid, you can use the `getFilterModel` method to retrieve the current filter state and save it (e.g., in a database or state management system). To restore the filter state, use the `setFilterModel` method with the saved filter state. This functionality allows you to maintain user filter preferences across sessions or reloads.
Yes, custom filters in AG Grid can access the entire row data. When implementing the `doesFilterPass` method, the filter instance receives parameters that include `data`, which represents the entire row's data. This allows the filter to perform operations based on multiple columns or complex data structures within the row.
AG Grid offers both community and enterprise versions. The community version includes basic features like sorting, filtering, and editing, which are sufficient for many applications. The enterprise version provides additional features such as row grouping, advanced filtering (set and multi-filter), and enhanced support for large datasets, intended for more complex enterprise-level applications.
To implement a dynamic filter component in AG Grid, define a React component that handles the filter logic and use `useImperativeHandle` to expose necessary filter methods to AG Grid. You can dynamically pass parameters like `filterText` or `criteria` through `filterParams` to customize the filter behavior based on the column or user interactions.
In an AG Grid filter component using React functional components, the `useImperativeHandle` hook is used in conjunction with `forwardRef` to expose custom methods. This setup allows AG Grid to call these methods as part of the grid's operations, such as determining if a filter is active or should be applied.
Video Transcription
1. Introduction to AG Grid and React
We're going to start off by creating an empty react project using create react app, react app. We'll install the necessary dependencies and open up app.js. We'll then install the aggrid React component and pull in some local data to display in the grid. We'll also specify the columns to show. Stay tuned for the agenda.
On the left-hand side, hopefully you can all see my screen, on the left side I've got the GitHub repo. We're going to use this to track the different chapters, if you like, or the sections of this talk. As we go, I'm going to be coding live. If you feel that you missed something or made a mistake or get a bit left behind, refer to the branch for the section that we're talking about and it will describe the code as we go. For example, in the first section, here's the code for the first thing that I'll introduce as I discuss, and then the second part, and so on. And at the end of it, so when we get to the end of that chapter, if you go to... We're about to start on the second section. So for example, if we're about to start the second section with enterprise features, if you just check out that branch, you'll be straight in line, back where we were. But as you go, if you want to follow along, just make sure that you've got the right branch for the section that we're talking about and the code's there. And you'll be able to copy and paste. Alternatively, you can code along as you like or you can just watch, you don't have to code at all and when you, after the workshop, take your time and go look at the GitHub repo and the YouTube videos that we have, and you can follow along in your own time.
So we're going to start off. We're going to create an empty react project using create react app, react app. We're just going to call it hello. Keep an eye on the Discord channel. So we're just a simple boilerplate react application here. It's nothing to do with the grid so far. Just installing all the dependencies. It's taking a time, I'm sorry. Wow, that took longer than I thought, sorry guys and Googles. Okay, so if we go to hello, we'll see a nor project. I'm gonna open this project up in my IDE. And as I said, so far, this is just a straightforward boilerplate React project. There's nothing specific about the AG grid yet. This was a lot snappier before, I apologize for the slight delay here. While that's having a thing, we'll go back to the terminal.
So to get started with AG grid and React, there are two dependencies you need to install. The first one is, we're gonna save it and save the dependencies. First one we're gonna install is AGgridCommunity. AGgridCommunity has all the core features and all the free features. You're able to use the features in AGgrid community without a license. You don't need to contact us. You can use us in commercial projects, and then that contains the core code. Then we also gonna install AGgridReact. AGgridReact is the React rendering side of things, so you need the two together. The AGgridCommunity is the core grid code, and that's part of the community edition, and AGgridReact you'll need as well for React integration, and that provides the React rendering. I will install those dependencies pretty quick. We've got your IDE. So the first thing we're going to do is open up app.js. Let me see if I can open up just in case people have questions. So if you guys or people on the channel have any problems seeing the screen or understanding me, please do feel free to ping a question and I'll try, and answer it. Okay. So we started off with React Create app provided to us. This is just a boilerplate code if we run this. We run this. Okay. The repo, I'll share on the repo. Someone asked, I'll just reshare that. So on the left-hand side, hopefully, you can see my browser. We see the results of the Create React app. I'll just share it. Okay. That's what Create React app has given us. So the first thing we need to do is install our aggrid React component. We'll pull it in. So we'll pull it in with imports. Aggrid React. We'll get rid of this stuff in the app, which we don't need. And we'll use our aggrid React component. So, so far, this won't do anything for us. Because at the minimum, a grid or table requires rows and columns. So the rows will be the horizontal things you see, and the columns will be the vertical. So let's pull in some local data to take a look at what that might look like. So. Focus. So these each of these fields will be something that we can put out and do in the grid. Row data is just an array of JSON data. You can have as many attributes, properties that you like, and then the properties can be complex. In this example, we're only going to be looking at simple data. So numbers and strings. But they can be of any type and then it will be the grid offers functionality for you to read that type and displays it however you wish. So in this case, we will put in some local data in the latest section and we're going to show you how we can more realistically pull this from a remote source. I would say this is 45,000 and this is 50. And then this one will do BMW. 4 series. So that's our row data. We haven't done anything with it yet, so it's. So that will tell the grid to display that row data. That's only half the story there because we also need to show and choose which columns to pull out. To pull out so your row data can have hundreds of fields that maybe you only want to show one or two. How you pick out what data to show is with the column data. So do that next. That's equal and like row data. This is an array of JSON data and at a minimum, you need to specify the field again to show we're going to have Make Model. And price. And again, we need to tell the grid. Good question. What's the agenda. So we've gone straight into it all, pause in a second and Tell you what the agenda is. Okay, so that looks all messed up.
2. Grid Features and Enterprise Functionality
We'll cover the basic functionality of the grid, including sourcing, filtering, creating cell renderers, and filters. We'll also touch on enterprise functionality and how to include it. The majority of the workshop will focus on community features and basic usage with React. The code for each section is available on the GitHub repo.
And that's fine because we'll get to that in a minute. So I'll pause for a second to discuss the agenda. What we're going to cover today I mentioned that briefly. But for those that have joined afterwards, I'm going to be describing some of the basic functionality provided by the grid. Sourcing filtering creating cell renderers filters and so on. I'll introduce you to a little bit of the enterprise functionality and how you'd include that. We don't talk a lot about the enterprise features. But if you're something you're interested in and you want to use that in a project will describe how you get a license, how you can try it and briefly, some of the enterprise features, but the the bulk of the talk. What this workshop will be free to use. Community features and just basic stuff really get you going up, get you up and running and going and you can see how easy it is to use with React. Yeah, that's it in a nutshell, these are five different sections and I'll just repeat briefly for those that join later. There's a GitHub repo and each of the five sections here is on the repo and it shows you the code for that particular section. If you want to copy and paste or if you make a mistake along the way and see what I've done, it'll be on the GitHub repo. I believe that answers that question, Clint.
3. Pulling Data from a Remote Source
We've pulled in the AG, installed the agigrid community and React dependency, specified row and column data, and passed it to the grid. We added CSS styling using the ag-grid CSS and applied the Alpine style. This is the minimum requirement for the grid to work. Most people will pull in data from a remote source, and we'll explore that next. We'll use hooks and React's useState to asynchronously set the row data. We'll also address CORS issues when running locally by using a data file from the main branch of the repo.
So, so far, we've pulled in the AG, we've installed the agigrid community and React dependency. We specified some row data and column data and passed it to the grid. And we can see the data displayed here, but as you can see, it's all messed up. So that's because we need to tell the grid we need to put in some CSS. And the thing that you're one CSS dependency, you absolutely have to put in is the structural agigrid CSS. And that is from agigrid community, list styles, agigrid CSS. At a minimum, you need to provide this.
Why is that not working? Oh yes. I forgot to provide a class name. I'll tell you why I'm doing this in a second. And the height. Normally you wouldn't hard code the height here. But just for display purposes, I'll describe why. There we go. So, this isn't important in this particular section. We'll come back to it in a second. So, here we specify the height. The grid will fill the parent's div. So in this case we have a simple div, we've set the height to be 500 pixels. In a real app, you probably have this as part of a larger application, but regardless the grid, the ag-grid components here, will fill whatever parent div you've given us. So, in this case, we've set it 500 pixels wide. And just to remind you, we've pulled in the bare minimum which is ag-grid CSS. And this provides the structural CSS that the grid needs. So in the grid, and the browser, we can see the three columns and rows. We can see make, model, and price. Which we've specified with column definitions. And we can see the row data, Ford, Toyota, and BMW, which we specified with the row data.
So, that's great. That's working, but that doesn't exactly look very nice. This is the bare minimum that you'll need to put in to work. And you'd pull this in and only this if you and your organization or your company wanted to provide its own styling. This is what you'd have to put in at the minimum for the grid to work. And then you could override the styles which we document how to do. But more commonly, you would use one of the styles we provide. So that's AG grid reacts. Styles. We provide a handful of styles. And we're going to use Alpine for this one. And this is probably the vast majority of what people do. So you can see now I've pulled in the Alpine style which we provide and specified it on the parent div. AG steam Alpine. And now you can see that the grid has got some styling. It's got rows, it's got the bolder field headers and so on. And there's a whole bunch of styles that we could try. Dark, for example. It's as easy as this. And if we change it to Alpine dark, you can see the theme changes to a darker theme. There's a material theme, balan theme. So go ahead and experiment but we'll stick with Alpine for now. So, at a bare minimum, this is what you need for a grid. You need the style in, pulled in. You need row data and column depths. And in almost no time at all, taking away my explanation, you'd be up and running with a simple, hardcoded admittedly grid in less than five minutes, I'd say. But that's probably not realistic for most use cases. Most people will probably pull in data from the hard data. The column data will probably be hardcoded, but the row data more realistically will be pulled from a remote source. Now, let's take a look at that next. Now, again, using hooks, which is what we're using here. And just to say that you can use hooks, you can use class-based components with grid, either within a grid or on the grid itself. It doesn't matter. We're using a functional component here but anything will work. But as we're using a functional component, we're gonna use date. And we need to do that so that we can asynchronously set the row data later on. I'll pull that in from React. Pull that in from React. Sorry, wait. What have I done wrong? This is the hazard of live coding I suppose. Okay. Everyone watching probably failed to monitor what I've done wrong. There we go. So we're back to where we were before, we've got the row data and the columns. Could I zoom into my IDE? Yes I can, let me make the font bigger. Hopefully this is easier. A bit better. Is that clearer Samuel? Please let me know, I'll zoom in further if that's not... Great. Okay, so we're back to where we started. We've got hard coded row data and column data. If you guys can't see or girls can't see a screen or anything I'm showing, please do ping and I'll respond as quickly as I can. So far, so good. We've got some row data and column data, but now let's go pull that data from a remote source, which is probably more realistic. When the hooks rendered for the first time, we'll want to... So I'll pause here for a second. When you deployed your app for real, this will just work. But as we're the one to get this data from a remote source, which has HTTPS and we ran in locally, yeah we'll probably get cause issues, especially with recent versions of Chrome. So what you should do for this demo purposes is if you go to the main branch, I've got a link on the repo for a data file, which is what we can read from them. Again, I copy that data. So OlympicWinners.json, you can find that again on the repo on the main branch. Just go to the data file and save that under public. And we'll call it OlympicWinners.
4. Pulling Data and Adding Sorting and Filtering
We'll use fetch to pull Olympic data from a remote source and display it in the grid. We'll specify the columns to show and add sorting and filtering capabilities. By using a default column definition, we can apply properties like sortable and filterable to all columns. We can also override the default properties for specific columns. Next, we'll explore events in the grid.
OlympicWinners. Now, this is only necessary to get around some cause issues. There's nothing special about this data. It's just Olympic data and it's something that we'll be able to use to display in the grid. So we'll use fetch. And here, we'll use a local. It's the OpenSUSE. Diamonds slash Olympicrecontype. Winners are Jaceh and then we need to get that array basin and tell it by tell it, put it back to Jaceh. It is what it is and finally we want to set that row data, that row data. But there's one other thing we need to do briefly and that's in the data we've just pulled in, we've got some different fields so we'll need to specify that. So in our simple data, we had make model and price but in this one, we're gonna use Olympic data which is a bit more and I don't wanna type these out so I'm just gonna copy these. Excuse me a second while I find a way to copy it. You know what, I'll do what I told you guys to do and girls to do. I'll describe what I've just done now once I've made sure it's all working. So let's go see, have I made any typos? Yay. I have made any typos. Okay, so I did a few things there and I know you are watching me type. So what I did firstly is save that Olympic winners JSON from a remote source locally. And that's just because if we're running local host, pulling data from an HTTPS remote source, Chrome will probably block us with cause issues and so on. So we just save the data locally under public and we use fetch data to load that data, convert it into JSON and then finally set the road data onto the state that we're using. We can remove the local data now. And then you can see we've got loads and loads of data. It's very realistic data. We've got loads of rows and a few columns. So, we've got athlete, age, country, and the medals that those participants have won. So, this is a little bit further than what we've done before, but more realistic. So, at a minimum, most of the time when you write in a grid or implement in a grid, this is the workflow that you would have done. You'll specify the theme that you want to use within the larger application. You'll specify what components, what columns, sorry, you want to display, and you'll specify the row data and pull it from a remote source. Doing just that with not too much code, you'll have a simple working grid. And this probably covers a good probably 80%, 60, 70, 80% of use cases you'll cover where you don't need complicated requirements and you just want to show some tabular data. With almost no effort, you'll be up and running. So let's take this a little bit further. Your users will probably want to, at the very least, sort and filter the row data. Perhaps they want to view the youngest athletes or the oldest athletes or order by country. That's pretty simple to do. We can add sortable, true, and filter, true, and if we'd save that, if we hover over here, just by adding sortable and filter, you don't have to do both. You can do one or the other. We now have sorting data, and we have simple filter here. We'll get into filters in a later section, so I'm not going to talk too much about that. But this is just to show that you can add sorting, filtering, and a whole bunch of other column properties very simply. So let's add filtering, and now we'll know we can sort by up until including dates, forward sortable, filterable. And, you may think this is very tedious and repetitious, and you're right. Say you want to filter every column, or you want to sort every column, you don't want to have to specify this over and over and over again, especially if you've got many, many columns. But let's take that out. We can specify column definition as a default across columns by specifying a default column depth. And this, whatever we specify in here, will be specified across every column that you have default. Column, let me just make sure I spell this correctly, default column depth equals memo. So, just to pause you for a sec, I'm using used memo. I'm going to use use effect, use state, use callback. I'm not going to describe why we're doing that. I'm assuming people know how to use these things in React already, because this obviously isn't a React workshop. Feel free to ping me on the chat or on Discord if you've got any specific questions why we're using it in GRID, and I'm happy to field it. But these are standard React things, and I probably won't get into too much detail about why we're doing something or the other with this particular React feature. So, we're gonna return an object, and we're gonna have sortable true, filter true, and we're gonna tell the GRID to use this. Okay. So, now we should have sortable, filterable in every column. So, every column now has sortable and filterable. So, you don't have to repeat to open it again. And this is said to just provide two property attributes. You could do sortable and filter, sortable and filter, sorry. And there's a ton more column attributes. I'll describe a few more as we go, obviously, but take a look at aggrid.com for the full list of attributes and what they do. So, as I said, this will specify any properties you want to specify across all attributes. Did I actually import? Yeah. But let's say you wanted to override it. You want to override the default, you could say here filter, false. So, what this will do is apply this to every column and then everything that you specified on locally will override. So, this one doesn't have filter now. It's still got sort, because we haven't overwritten that, but the filter is gone because we've overwritten it. So, the order will be default column def, and then everything you specify locally will take precedence and override that. But for now, we've got a simple grid that has sorting and filtering on every column. And as I said, we'll talk about filters a little later on. I've got a whole section on filters and then custom filters. So, I'll defer any discussion about filters for now on. Just know that we provide about three filters out the box that you can provide and use. And in Enterprise Edition, there's two more out of the box that you can use. And then, of course, you can write your own custom filters in React. Petros, just use the Zoom channel. Don't worry about Discord. If you can ping here, I'll answer questions as I can on the Zoom channel. Don't worry about Discord if you can't reach there. Okay, so, so far, so good. Let's say now we want to act on some event. Let's talk about events next. So, like I said, for all the list of column properties, and there's so many, I couldn't possibly discover them in a workshop, go to adriagrid.com, look at column definitions and see all the properties that you can use on a column and how to configure them and how to use them. So, this is just to describe it in high level terms. We've said, forSpring and forSportsPring. Let's take a look next at events.
5. Exploring Grid Properties and Events
We'll explore additional grid properties such as virtualization, animation, and row selection. Virtualization is enabled by default, both vertically and horizontally. We'll also cover grid events and accessing the grid API and column API. You can use the APIs to perform various operations programmatically, such as resizing columns, enabling sorting and filtering, and getting column states. In this example, we'll use the grid API to deselect all selected rows. Visit aggrid.com for a full list of properties and methods.
Say we wanted to, when a user clicks on a column, we want something to happen. Perhaps they click on something and we want to, perhaps they're looking at a shopping, a whole bunch of shopping items and they click on something and it would pop up with an image to show what a chosen item might look like, for example. We won't do that, we will do a console.log or an alert. But first things first, we want to add, oh, you know what, before we move on, I'll look at two more grid properties that you might want to do.
Unlike column properties, there's a ton of grid properties that you can do, tons. So, Bruna has just asked, is the table virtualized by default? Yes, it is. There's a certain amount of rows and columns, plus extra, a little bit of buffer. So, let's say we only seen 15 rows there. I'm not sure how many rows we've seen, but say we only seen 15 rows. It will show 15 rows in memory and render them plus another two or three. I can't remember what the default is. And then the data after that will be virtualized. And then only as you scroll will it be rendered and all the things that are no longer in the Viewport will be pulled out. Take a look at the documentation for virtualization and how you can override that, but yes, by default virtualization is enabled, both vertically and horizontally. I've talked about column properties. Let's take a look at the grid properties. Again, there's dozens and dozens of properties that you can use here. We'll use two just to demonstrate how you might use it. First, we'll animate rows. And the console warnings you might see in the IDE, you can ignore those. These are in a real application, you could do something about it, but these are just warnings. And for the workshop purposes, you can ignore those. So we've added animate rows now. So before, there wasn't animation, animate rows, what did I, let me see here, animate rows, true. I need to refresh, I think. Oh, okay, that's refresh. So the hot loading's great, but it doesn't always fully refresh. So hopefully you can see before now that there's a animation there. And that's a cool animation effect, which I quite like. And we've enabled that with just animate rows to be true. And let's add some row selection. Row selection, and this is just a string, so we can just use this, mobile-to-pool. And now we can select rows by holding down Command or Shift. And what I'm trying to demonstrate there is we've talked about column properties, sort of on filter, and now I'm just introducing you to grid-specific properties, so animate rows and row selection. And it's as easy as just providing the property and setting it to an appropriate value. And all we did with there was enable animation of rows. You can see that cool animation and row selection. And all you had to do there was to set up property. So, so much of the good functionality is unlocked just by enabling set into true or setting a default in the property. There's so much power to unlock with simple properties and values. But again, for all the list of properties on columns and the grid itself, go take a look at aggrid.com.
Okay, so moving on, like I said earlier, we'll look at events next. Now we want to look at clicks. So first thing we'll need to do is we'll need to get the grid API. There's a couple of ways of doing this. One is with events. And the better way to do, especially in React is to use a ref. So I will say, grid ref. I'm doing it a little backwards here. So we're gonna say, we're gonna pass down a grid ref. We haven't actually specified it. So const grid ref, equals grid ref. And we'll import that. Okay, so that obviously doesn't do anything so far. We've specified a ref at the top here, and we've passed it to the grid, then others will be set when the grid's rendered. But we're actually gonna use this to create a button that's gonna de-select any rows that we've selected. Uh, I've skipped a step, I apologize. I'll come back to events in a sec. Sorry, I'm getting a bit out of order. Let's say we want to do something with this. So when the user will create the button, apologies for the weird order. I will pause again once I'm done and describe what I'm doing here. Okay. What I'm doing here, I'm just going to demonstrate how you get access to the grid API and column API, and then how you can use it in a button, for example, in this case, but in any number of cases, but in this case, we're just going to use it in a button. Push me calls use callback. I'm not actually doing anything with the event the grid ref dot currents. We're just going to say, grid ref dot current, give us the current reference to the grid component AGGrid React. And in this case, we're gonna use API. That will give you access to the grid API and also column API. And that's for column API operations. We're not gonna use column API in this particular example. We're gonna use the grid API, which is to deselect all. We're gonna use column API. All right. So we've got a button here. That will say, let's assume we've selected these rows and we want to provide a functionality to the user that will deselect all selected rows. And there we go. So I did that again. I've selected a bunch of rows, push me is going to fire when the buttons clicked and using the Mr. people I've done grid ref.current will give you access to the ag grid react components. And on the ag grid react component, we've got two fields, the API, which I've highlighted there and the column API and a column API. And the API provide a whole bunch of functionality you can do programmatically. You can resize columns. You can enable sorting, filtering. You can get one column States. Again, these dozens and dozens of methods that you can use Please look at aggrid.com for the full list, but in this simple use case, I'm just trying to demonstrate that we've got access to the APIs by setting a ref. And then in this case, when the button's click, we're using the grid API deselect all to deselect all selected rows. So just to show you again on the browser, I've selected a bunch of rows. When I click this button, I'm going to call the grid API and deselect everything. Okay.
6. Events, Themes, and Agigrid Enterprise
We'll discuss events in Agigrid and how to add listeners to columns. You can listen to various events like cell clicked, and perform actions based on the event data. The grid API provides access to the row and column data, allowing for programmatic operations. We also covered how to create a theme for Agigrid, either by tweaking an existing theme or creating one from scratch. Next, we briefly mentioned using Agigrid Enterprise and its features. To implement Agigrid Enterprise, install the Agigrid Enterprise dependency along with Agigrid Community and Agigrid React. Finally, we addressed the best way to confirm that the grid is loaded, suggesting events like grid ready and first data rendered as indicators.
Hopefully that'll make sense so far. And the last thing I'm going to describe as events, which is what I referred to as earlier, but I didn't actually describe, so let's just do that now. So there's so many listeners as well as with APIs and color definitions, good properties, look at the grid documents at aggrid.com for all the things that you can listen on. In this case, we're going to listen to a cell clicked. When a cell's clicked on, we're going to alert out and we're going to alert that something's happened. Callback, E. Control.log, cell and whatever we're passed. And to use that, click and drag truncate plus two, there we go.
So, just to repeat before we talk about the browser, I've specified a listener that we're going to use here, using useCallback. When the grid responds to an event and passes it up, bubbles it up to you, it will pass in the params and you can do something with it. So you might want to alert the user that they clicked on a cell, you might want to perform some sort of computation, et cetera. In this case, we're just gonna output control.log cellClicked and what the grid's passed us, which we'll look at in a minute, And to hook in an event, all we had to do was specify the event we want to listen to and pass in a listener. So if we go and look at the browser, you can see that every time I'm clicking on a cell, a console.log message is being printed. And when an event's fired, depending on the event, you'll get API, the columnAPI, you'll get the row data, you'll get the cell data. You can get just about everything that you might want to use in an event listener. You'll get the row data, the column data, the access to the grid, and so on. In this case, we're just printing that out. But hopefully that demonstrates how easy it is to add a listener to an event, to a column. You can listen to sorting, you can add filtering. Anything that you might conceivably want to listen to, you can in the grid, just check out edugrid.com for what events you can listen to and callbacks you can listen to, and you'd implement it like this. Hopefully, that'll make sense so far. Let me just take a quick look at the Discord channel. No questions there, great. Okay.
So that briefly describes getting up and running very simply with the Community Edition. We're going to go into more detail in the subsequent sections. But this is just to remind you what we did. We pulled in the edugrid React components, we pulled in the styles. Remember, you need edugrid.css as a minimum, that provides the structural CSS. Without that, the grid just won't work. And then you can optionally provide a theme. 99% of the time, you're going to use one of the themes that we provide. And then you specify the theme that you're going to use on the parent div. We specified the bare minimum data that you need on a grid. You need the row data, which is the horizontal data, and then the column data, which are the fields you pick out of row data. Here we specified the field we're interested in, and we pulled in some remote JSON, which is an array of JSON objects, converted it to JSON, and then set the row data, which is then displayed in the table. We've also set some default column definitions so that all columns are sortable and have a filter on. We then described how to use the grid API, in this case, for the button to deselect any selected rows, which we can just exercise now with mouse. There it is. That row is deselected. And then finally, I described how we can use events. In this case, we added a cell clicked event. And we added a listener that can listen to those events. And before I forget, we also added two column, I'm sorry, grid properties to animate rows and add row selection with these two properties here. So what's the recommended way to create a theme for Agigrid? Can the theme tap into? So I'm not sure about the CSS in GIs theme providers, I don't see why not. With how to do it, you'd have to go to the styling section of agigrid.com, and it describes the structural CSS as it's laid out and how you'd override them. I'm not too familiar with that side of things, but it is documented on agigrid.com on how you provide your own theme. I think what a lot of people do is take one of the provided themes and then tweak it which is a lot less work than creating a theme from scratch. So that might be something you want to look at, look at the themes that we provide out the box, see which one's closest to the one you want and then just override it with CSS, with SASS variables and so on. But if you really want to do something from scratch, we document how to do that too on agigrid.com under styling, I think.
So we'll move on to the next section, which is a brief second. It's just how you would use Agigrid Enterprise and some of the features provided there. But as I said at the beginning, this is not really about Agigrid Enterprise specifically. If you want to use Agigrid Enterprise, contact us at info at agigrid.com for a free trial license to try out the features. But this is just a brief section to say how you would implement it, how you would put in the Enterprise features and use it. So to check out the code for that, make sure you've selected to dash Enterprise, and that's the second section that we'll cover now. So we'll stop our... Okay. Nina, don't worry about the Discord channel. You can just use the Zoom channel as you're using now. I'll look at that. It seems like other people are having Discord issues. Just use the Zoom channel, Zoom chat. That's fine. So the first thing we're going to do, we've stopped our app that was running. I just have a quick sip of water. The first thing we need to do is install the Agigrid dependency. Agigrid Enterprise. So this is going to install and save the Agigrid Enterprise dependency. As I said at the beginning of the first section, at a minimum, you need Agigrid Community and Agigrid React. Agigrid Community is the core community code. Agigrid React is the React rendering side of things. And then Agigrid Enterprise pulls in the Enterprise features. You need both Agigrid Community and Agigrid Enterprise. Agigrid Enterprise doesn't include Community. It imports from Agigrid Community and uses that to extend its functionality. So you need all three for Enterprise code. Agigrid Community, Agigrid React, and Agigrid Enterprise. What's the best way to confirm the grid is loaded? Best way to confirm the grid is loaded. I can inform the user too. Uploaded. I can inform the user, playground, to the grid. What I think the best way to tell them, there are events that you can, so we talked about events earlier. And there's first data rendered events and a grid ready event. Both of those events would probably serve your purposes. So when those events are fired, you can tell the user that the grid is ready and data is in the grid and displayed. So in your use case, you'd either just see the grid, but if you needed a programmatic way to let the user know, there's a few events that you could fire it on. Grid ready, and first data rendered events. You can listen to those events and then maybe show a pop up or a modal or something to let the user know that the grid is ready for inspection. Hopefully that answers that question.
7. Using Aggrid Enterprise and Recap
We pulled in the Aggrid dependency and imported Aggrid Enterprise to unlock additional functionality. By doing so, we can now export data to CSV or Excel, copy data with headers, and apply advanced filters. We can also group data using the Row Grouping feature, allowing users to view the data in a customized way. The enterprise edition offers a wide range of features, and while most functionality is free to use in the community edition, specific enterprise needs may require an enterprise license. Contact us at [email protected] for a free trial license or to purchase a license. Let's recap what we covered.
OK, so we've pulled in the Agygrid dependency, let's start up our application again. We pull in the dependency but we're not actually using it yet. So if we reload our application you'll see what we had before. So to import the dependencies, all you have to do is import Agygrid Enterprise. So by doing that alone... Actually, you know what, let me comment out, let me show you something. So without Agygrid Enterprise pulled in, you'll see the default browser context menu and when you look at the filters you'll see the pre-provided filters which is a very powerful filter. And you can get number, date and string filters. But we will talk about that in a later section. But you'll see that the default one is this, and then the context menu is just your browser context. So out of the box if you just import Agigrid Enterprise and reload your app. First thing you'll see is a console message saying that Agigrid Enterprise, a warning message, just telling you that you don't have a license key. That's fine. It won't, no functionality is disabled. You can use Agigrid Enterprise, trial it for free. If you want to get rid of this console message, you can contact us at info at agigrid.com and we'll give you a free trial license. So you're free to try around and play around with Agigrid Enterprise and play around with the features. And then if you decide to use it in an application, you can contact us for a license, but no functionality is disabled. You'll see a little watermark and a console message, but all functionality is enabled. So that aside, if we then go and right click, you'll see now some functionality is unlocked straight away without you having to do anything other than import Agigrid Enterprise. You'll see you can export down to CSV or Excel. You can copy group headers and so on, and then if we look at filters, you'll see now you've got column panels. You've got things where you can pin columns left and right, you can auto-slide those columns, you can hide and show fill columns, or the user rather can do this. And now we have a different type of filter that we had before. We've got a set filter, which is the set of all data underneath. So now in the Enterprise, the default filter becomes the set filter. And again, I'll describe filters later on, but just to demonstrate that you've unlocked the enterprise functionality just by installing the dependency and then importing it. Now, let's say we wanted to take that a bit further. So that's great. I mean, being able to export your data is useful, especially to Excel for a lot of users, but you can also copy data. So a user could select some rows for example, and then copy the data by right-clicking on it or copying it with headers and so on. But let's take a little further. Say you wanted to, we've got a lot of data here. So that's not especially useful, even with sourcing and filtering, which is great. Perhaps people want to view the data we've seen, but group it, and that's really easy to do. So we can do that by using the enterprise feature called Row Grouping. So let's group by country. And just by doing that, you can see that the data now is grouped by country. So we've still got the same Olympic data we had before, but now grouped by country. Let's say we wanted to group by year as well. It would group by country and year. Whoops. So I'm only refreshing because the hot reloading sometimes causes issues. So now you can see that just by adding row group true, we've grouped by country and then year. And all we have to do is specify row group property. And now you can do this programmatically up front. Say you wanted to provide a default report to users out of the box, where you don't want to use change data, you can provide out-of-the-box. But you might want the users to be able to view the data in a way that they want to view. So in that case, you could provide this functionality by firstly showing the drop zone, the grid drop zone. I'll describe that in a second. So we'll add row group panel show. Wait. Let me look at the property. Row group panel show. Always. So I've added a grid property called row group panel show. This is a drag zone for various functionality. And in our case, we're going to use it for row grouping. But you see by adding that property, we've got a header at the top with drag here to set row groups. And that's great, but we also need to tell inside which groups can be dragged. So you might have data where it doesn't make sense to be able to group by certain data. Maybe you've got dates with milliseconds, and it wouldn't make sense to be able to group by that potentially. So you'd want to be able to specify per column what data you want groupable. In our case, we want every column to be groupable. So again, we'll specify this as a default column def, instead of having to specify to every one. So enable row group, and this will make that every column is groupable. We can save that. Refresh our grid. And now we can do what we did before. We can group by country, just by dragging it. And what I did there, in case that was not obvious, was I selected a column, clicked on it, and then dragged it to the drag zone at the top. And then to replicate what we had before, drag year up. And then we had what we had before. We've got row data grouped by country, and then year. And this is useful if you want to provide the raw data to the user, but you want them to be able to cut and slice and view the data in a way that they choose. All you had to do there was specify enable row group and tell the grid that you always want the panel to show. So again, with very little effort, you can unlock an awful lot of data for the user. Now I'll just very briefly finish off on the enterprise section. There's a ton of section, ton of features that you can use with enterprise features. If when you're looking at aggrid.com and you see a little e next to the feature that means it's an enterprise feature. I'd say probably 70% of the functionality we provide, 80% of the functionality I'm guessing is free to use. So most of the functionality you want to use in the grid is free to use and it's a community edition. But if you have specific needs or enterprise needs, then maybe you need to use aggrid enterprise. And if you see a little e next to it, then you'll need an enterprise license. But again, you're free to use aggrid enterprise and try it out. And if you want a free trial license, contact us at info at aggrid.com. And then you can also take it further and actually buy a license if that's something you decide to do. So I think I'll leave that at aggrid enterprise. I assume no one's got any specific questions. I'll just recap what we did.
8. Installing Aggrid Enterprise
We installed the aggrid enterprise dependency with NPM and saved it into package.json. The free dependencies are aggrid community and aggrid React. To use enterprise features, add aggrid enterprise. Make sure your major and minor versions are in sync.
So first we installed the aggrid enterprise dependency with NPM and save this into package.json. You can see here the free dependencies we have, we have aggrid community, which is the free community edition, which has the 78% of the code functionality that you need. Aggrid community is free to use, you don't need a license for that. Aggrid React is the React rendering side of things. So at the minimum, you need aggrid react and aggrid community. Then if you want to use enterprise features, you put in aggrid enterprise and you need that as well as the other two to unlock the enterprise features and that builds on top of aggrid community. And lastly, you need to ensure that your major and minor versions are in sync. You want to always have major and minor versions in sync, so you don't ever want to have 27.4 and 3, for example, and mismatch. For patch versions, these can be different, that's fine, but you want to ensure that your major and minor versions are the same across the penalties you use.
9. TypeScript Support in Aggrid
Aggrid supports TypeScript and provides all the necessary typings. You can use it with TSX and benefit from auto-complete. It's highly supported and even written with TypeScript.
Yes, aggrid support TypeScript. We ship all the type ins that you'd want to use. We document how you can use it with TSX, for example. So, for example, if you wanted to use a grid ref, you could specify it as aggrid react, something like that. I can't remember the exact type, but we do document how to use this, and yes, the typings are exposed for you to use. And if you did something like this, you'd have auto-complete. So, yep, it's pretty supported. Aggrid react, aggrid's actually written with TypeScript. You don't have to use TypeScript, but it is supported.
10. Using Custom Renderers in AG Grid
The grid can show raw data from the JSON data provided. You can use a React component as a renderer, replacing the raw data with custom output. The grid passes props to the renderer, including the value of the cell. By using the provided props, you can customize the output of the renderer. You can also pass additional data to the renderer via props. This allows you to create generic renderers that differ only by the props passed in. This flexibility allows for complex rendering within the grid.
Okay, that finishes off enterprise features. Next, we're going to look at, I'm going fairly quickly. If you have questions or if you want me to repeat something, please do ping me on the chat channel and I can repeat it. Um, so we'll go on to the third section, which is renders. And this is using custom renderers. So out of the box, the grid will show you raw data and it'll show the raw data. So for example, here, Michael Phelps, United States, 23. This is simply printing out the raw data that's in the JSON data that you provide to the grid. If there's string, it'll show a string. If it's a number, it'll show it as a number, it'll show a raw number. If it's a complex object, you'll probably just get object objects, but you can, with value getters and so on, pull out past complex data and print it out. But ultimately, what a user will see will be a string representation. Or sorry, something like that, simple data. But what you can do is provide a React component. So perhaps you want it to spin in Will or a slider or anything. Anything in these rows and columns, including headers and filters, can be React components. So in this first section, the document will describe how you'd use a cell renderer, which is probably the most common thing that you'd probably wanna create a custom renderer for. And anything that you can do in a React component, you can pop into the grid. So the first thing we're gonna do is we're gonna have a simple, not very useful but a simple renderer, my renderer. And this is just gonna show... Sorry. We've got a simple renderer here and we're gonna use this renderer on the app-node column. So, this is not a terribly useful renderer, obviously. But again, we've got a simple functional component and we pass it, we tell the grid to use this component, my renderer. And we want to use it in place of a cell renderer. So instead of representing our outputs in the raw JSON data, we're gonna output whatever the renderer does. And in our case, regardless of the underlying data, we're gonna show hello world. And now that's not terribly used, right? Every row has hello world for the athlete column, so that's not terribly useful. So let's take a look at what the grid provides us. When we render each column, we can... Give me a second, a water. Whenever each row and cell is rendered, if you've got a custom renderer, we'll tell the grid, we'll call your renderer and instantiate it and pass down the state of the grid and the cell value and so on. So let's take a look at what we passed you. So let's take a look at the props that the grid passes. So you'll see a whole bunch of outputs here and each row will output the P, the props passed to the components. And if we expand any one of them, you'll see a whole bunch of useful stuff. I won't describe all the things that are provided to you, but some of the key ones are the column depth, the column information, you can see the API and the column API provided to you. But the thing that you'll use most typically and most commonly is the value. You'll see at the bottom there, the value merits the organ. And that's the thing that you would typically use most common, but we provide a whole bunch of other things that you might want to do as well, like the APIs, for example. So let's make this renderer a little bit more useful and let's use the data we're given. So p.value. And with that, we should end up with what we had before. So we're using visually from the users perspective, we're seeing what we saw before, the rows and column data, and we're seeing Michael Phelps and the raw string data, because we're not doing anything special with it yet. We're simply taking the props and pulling off the value bill and outputting it. So we're left with what we had originally. But let's say we wanna do something a little bit more realistic. Let's say that in a renderer, we wanted to have a little button, perhaps we want to do when a user clicks on the button, add an item to their shopping cart or so on. So let's do something like that. Not quite a shopping cart, but let's do something with the renderer that's a bit more complicated. So const on dollar, I mean, this is not terribly useful as well, but it could just demonstrate the point, you got value and I want this to be a string, so here we go. So we say that and I'll describe what we've done, if we look on the browser, we can see a button that says Kipme, it actually should say dollar. That's why the business is called dollar. So we've taken our simple renderer and extended it very slightly. We've now got an Avengers now that's gonna be fired when the dollar symbol is clicked and it'll output dollar clicks and the value of that cell. So again, this is a very simple render, right, this is not something you would probably do, you'd do something much more complicated. But let's take a look at that, so if we click on that, got dollar clicks and then the value of the cell, Nathalie Coaglan, which is the value of the cell we clicked in. So again, this is really simple, obviously, you'd probably do something more complicated with your data, it's just to demonstrate that any react component that you have can be rendered within the grid. Let's take that a bit further, let's show you how you can compliment the data you have. So by default, when you have a renderer or an editor or a filter or a custom filter, you'll get the state of the grid and the value of the cell you clicked on or so on. But you can compliment, you can add to via props data that you want. So let's take this further. Let's say that... Let's say we wanna pass down the button text. So you want a generic component and you want it only to differ by what you pass in. So you can compliment it with an object and whatever you specify in here will make available in the props of the components as it's dynamically created. And whatever you put in the dynamic, the params can be anything. Excuse me, one second. Sorry about that. So we don't do anything with the state and we'll simply make this available. Now case we're gonna do button text. I'm gonna say the button text is gonna be app-lete-button. And that will now be available to us on the, if we look at this, we look at the data, the stuff passed in, you'll see button, what do I call it? I think I made a typo, cellrenderer. Renderer. It helps if you spell properly. So I made the typo before, I hadn't spelled cellrenderer correctly. So if we look at this, we've said on the app-lete column, we want to provide a prop called button text with a value of app-lete-button. And if we look at the prop path to the renderers, you can see that the props are being rendered and the prop path to the renderers, you can see button text is made available. So let's use that. So instead of the button being called dollar, we could pass in here p.button text. And you can see that in the red browser, we've got app-lete-button. So for example, you might want to use this renderer, make it a generic renderer, and to be differed across columns only by props that you pass in. So let's just demonstrate that. Renderer, make it generic. And we'll describe this a little further later with fields. And this could be age button. So you can see that we've used the same components, this renderer here, and we've made it generic. And we've differed only by the props we passed in, button text in this case, but it could be anything. That's just to demonstrate how you can complement the renderers you use and provide some extra metadata or props to them.
11. Using Renderers and Filters
We discussed how to complement renderers with extra metadata or props and demonstrated the use of inline renderers. We also explored dynamic cell renderers and how to choose different renderers based on column data. The size of the rendered components affects the row height. We moved on to the next section, which focuses on filters. In the Community Edition, we provide three out-of-the-box filters: text, number, and date filters.
That's just to demonstrate how you can complement the renderers you use and provide some extra metadata or props to them. Lastly, I'm gonna show you how you can use a simple renderer and this is an inline renderer. And this is probably something you might wanna do if you're doing testing or that was a super simple renderer, something you're not gonna share. You can just use an inline renderer. So you don't need to specify it externally. You can say something like, my inline renderer, p.value. So this is the same as above really, but you've got your in the browser, you see my inline renderer and the value. So you can finally specify something inline, you don't have to externalize it either into a separate file or into a separate const like we've done here. If it's super simple, or if you're just doing debugging or playing around, you can inline it as I've done there.
Okay, so what's next? So let's say that you've got a scenario where you want to have different renderers based on the value of the column. So you might want to say, renderer X if the data is one and renderer Y if the data is two, you can dynamically choose what you gonna show based on cell renderer selectors. Let me show you that. So you can have it static and that's probably the most common use case where you'd specify it like this, but you can have a dynamic with cell renderer selector. And that's a function that returns an object. And again, just to remind you, this is where this is the use case if you want different renderers in a cell and you want to dynamically switch between them to based on the row data or some other external factor. In our case, we're gonna do it based on row data. So, if the value is equal to 2000, we're gonna return and specify components, my renderer. We're gonna use this on a different field actually. If p.value equals 2004, we're gonna return, I'll describe what I've done here in a second. In this case, we're gonna have a inline components. I'm just gonna move this to another field. I want this to be on the year field. I'm going quite quickly, but I will describe what I've just done here. I've moved this, I've added a property called cell render selector, and that's fired per row data for this column, for every row in country year column. This will be fired. It'll pass down P, which has the API, grid API, the row data, and specifically the cell value for that cell. And what we're doing here is we're saying if the value, or if the year value is 2000, we'll return my cell, my render, the one we specified above with the button. And if the value is 2004, we're gonna create, return a simple inline component, and if the value is neither 2000 or 2004, we'll just up with the raw value. So let's save that and see what happens. So, here you can see for this value, for this row, the year value is 2008, we haven't specified what to do with 2008, so the grid will simply output the raw data. If the value is 2004, we're gonna return this inline component here, my inline components and add the value, and finally, if the value is 2000, we're gonna use my render with the button, as we said before. So, if you want some rows to have a special functionality or render, you can dynamically use, do so, with my cell-renderer selector. Whatever renderer you do, you use, you can still compliment it with cell-renderer params, as I've done here. So, for example, in, am I muted? Gosh, I'll take a look. I don't think I'm muted. Can anyone else hear me? Not to me, it's not, great. Woo, I'm glad to hear it. So, I'm sorry for Joe, it must be something on your end, I'm afraid. So, just to repeat, whatever we return, if it's a custom renderer, we can compliment it with cell-renderer params, and whatever we do in cell-renderer params will be made available in props. If you don't specify a component and a renderer to use, the grid will simply output the raw value of the adjacent data. I hope that makes sense. So, yeah, sorry, Joe, I'm not sure I can help you. If other people can hear, it must be something on your end, I'm afraid, but I don't think I can help you, Joe, apologies. Well, you can't hear me, I suppose. So, just to recap, we described how you can specify a cell-renderer. All you need to do is cell-renderer and then your renderer, so in this case, MyRenderer like that. You can also have inline renderers, hello, like that. And finally, you can have dynamic cell-renderers and you can choose different renderers based on the column data. Hopefully, that makes sense to everyone. That was pretty quick. I'll just take another sip of water. Just to recap, we remind you that the renderers I've done here are pretty simple. They simple, they've got simple buttons and simple data, but you could have anything. You could have a graph or a dynamic slider or spinning wheels. Anything that React can render in our components, functional or class-based components, you can render within the grid. The size of the components would obviously change the size of the row. So if you had those components with athlete button, and if you had those 30 pixels high, the whole row would be 36 pixels high to show that, but this point is anything that you, any React components you want to render in the grid, if it's a valid React component, it can render in the grid. How does the cell render if the line's too long? Okay, so I've kind of answered that. If you had a component, say, that was outputting a multi-line component with images and so on, it would fill up that height. So for example, if you had something that was outputting an image that's a 100 pixels high with a paragraph next to it, then the entire row, so this column, would be that high, 100 pixels high, with text next to it. So the whole row would be 100 pixels wide. The row height is determined by the highest, the biggest cell in that row. So if all the other rows, cells are 20 pixels high and the dynamic renderer has 100 pixels or higher, it'll be a 100 pixels higher, it's fairly dynamic. Yes, it is Bruno, it's dynamic. Yes, you can override that. You can say that you absolutely want your row heights to be 50 pixels and everything else to be clipped, for example, but by default, it will be dynamic. Have another simple water here.
Okay, so we'll move on to the next section. And it's going further with custom renders. And so, no it's not, it's called commit filters. So we're gonna touch on this section, on Filters. In the first section or two, I showed you how to enable filters, and out of the box with Enterprise Edition, you get set filter as a default, which is something we'd see here probably. So you see this is a set filter, which we'll describe later on. Let's remove the Enterprise functionality, and refresh. Don't worry about this error message. And we've gone back to a simple filter. So this just to discuss, for initially, for now. We provide out of the box three filters out of the box in the Community Edition. Again, the Community Edition is free for you to use, and commercially, you don't need a license, and out of the box, we provide a text filter, a number filter and a date filter. So let's go through those one by one. I'm gonna remove the renderer code, just for simplicity. Remember the code is on. If you wanna recap what I've done, just go look at the Github repo for the particular section you're interested in. It'll be there. I'm just gonna remove this code so we can see just what I'm trying to describe. Let this net can go. And there we go. So we're back to a simple Community Edition. There's no Enterprise Code here now. The first thing we're gonna look at is the text filter.
12. Filtering Data in AG Grid
Out of the box, the filter true is good enough for most people. Custom components, renderers, editors, and filters are free to use in the community edition. The Rogue Grouping feature is an enterprise feature. Rows and columns are virtualized by default. The provided filters are very powerful and can take you a long way before needing custom or enterprise filters. The number filter provides context-sensitive filtering for numbers. The date filter expects cell data to be a date object. The enterprise filters, column filter and agmulti filter, require an enterprise license.
And that's, if we just do filter true, depending on, give me a second, Towson, I'll provide the link. I hope I'm saying your name correctly. So that's the repo. And then just to recap, in case you missed it, for the section, if you go to the branches, each branch, each section is a different branch. And if you click on that section, it'll see the code for that section. Okay, so thank you, Oskander? I'm probably massacring your name, I apologize. But each of the branches is a section. So we're on section four, and it'll show the code. So, for example, if you're trying to work along with me and you've made a mistake, you can, afterwards, go look at the code that I actually typed. So go back here.
Out of the box, if you just say specify filter equal to true, it'll use the default filter for whatever code you were using. So if you're using the community edition, it'll use the text filter. And if you're using enterprise edition, it'll use the set filter. So, most of time, the filter true is good enough for most people. You'd probably want to use the default issue. Renderers are, no, no renderers are not enterprise edition. In fact, most of what I'm describing here is community. Custom components, renderers, editors, filters, which we'll get onto in the next section. All of those are free to use. I will highlight, and I'll specify if something I'm doing is enterprise, but like I said, right at the beginning, most of the talk, most of this workshop is community edition. I'll highlight if something I'm doing is enterprise. So custom components of any type are community edition. So whenever, if you're doing a custom React component and you want to use it in the grid, that's free, you don't have to use an enterprise license for that. So the Rogue Grouping that I showed you by grouping by year and by country, that was an enterprise feature, for example. But everything else you see in this grid, now, is free, including the renderer you saw before. That's all free to use. Yes, rows are virtualized. Out of the box, you can override that, but yes, the rows are virtualized and columns, actually. You can override that, so caggrid.com for details on how to override that, but by default, yes, they are. And so that'll, so filter tree will be the default filter. It's the same thing as if we did agTextColumnFilter. And I'll go through all the three ones provided. So if we do that and we look at the filter, you'll see nothing's changed. We can still use Mic or Michael or Jung for Jung. And although this is the free, out of the free edition, and that through all three filters we're going to describe are free, they super powerful. So don't think that just because it's as free and provided without a need to get enterprise code, they're not powerful. These are super powerful and can probably take you a huge amount of way, a new way to an application before you need to consider a custom filter or an enterprise filter. The provided filters are very powerful. So check out agigrid.com for what they can do. I'll describe briefly here, but they are very powerful and can do a lot more than you think. So in this case, let's say we don't want contained. We want equals, exactly equals. We can say, that doesn't do anything because it's not equals not contains, and now Michael Phelps is there. So, and then you can provide all functionality. So let's say we wanna do contains Michael that gives me everything with Michael in, but we only want it and if it contains maze. And you can do all. So Michael or maze, and as you can see, that's just the text one can do a huge amount of things. So let's take a look at the next filter that's provided out the box. And this is the number filter. Again, this is free. None of this is enterprise specific yet. If you see an error in the console here, by the way, that's not to do with the grid, that's just hot reloading. Sometimes it doesn't fully refresh. So if we look at the age filter, you'll see that now we've specified a number filter, not a text one. And it's equally powerful as the text filter, but it provides things that are context sensitive. So for example, it doesn't provide contains, but it provides greater than, less than and equals. So you could say it's less than 30 and it's greater than 20. And it dynamically, everything, all the ages of these winners between 20 and 30 are, so I said equals, I mean greater than. So all ages between greater than 20 and less than 30 are displayed. And that's the number filter. So it's similar to the text filter, but it does number appropriate filtering. And then the last thing, which won't work, and I'll describe why it won't work, but the last thing, and I'll show you how to fix it, is filter AG date column filter. Now this will provide a cool date filter, but unfortunately, this won't work. So let's take a look at the first one. It's 2408, 2008, 2408, 2008, but not 2008. And that doesn't actually work. You'll notice that the date didn't filter. And the reason for that is that the date filter expects the cell data to be a date object. And the data we have here from the array, this data here, is as you can see, it's just the string. So it looks like a date, but it's actually just a string. So when the date filter has been applied and trying to use, none of these will match because they're just strings. Well, I'll show you how to fix that later on. Now, we're going to use two, finally to show two more enterprise filters. So we're gonna enable. So these are enterprise filters. So you would need an enterprise license for this, but this just rounds off the filters that we provide out of the box. These three so far, the text filter, the number filter, and the date filter, those are free and in the community edition. The next two filters are enterprise. And I won't spend too long in this. And I just wanted to just describe what they do. So, you know, column filter. And the last one is filter, agmulti filter. So again, the warning console again, because we don't have a license key. But if we look at the country, you'll see now this filter is a set filter. The set filter, it provides a set like you'd see in Excel, same sort of thing, and provide a unique set of all the values in that column. So for example, these countries are pulled from the row data. So if you had extra or fewer countries, only those countries would appear here. You can select, deselect them all, and then select one by one or select them all. Or you can also have, choose something here and press enter, which I think is pretty cool, and filter it. So for example, I'll just show you what I did again.
13. Using Set and Multi-Filters in Agigrid
The set filter and the multi-filter are powerful filters provided by Agigrid. The set filter allows for dynamic selection of data based on specified criteria. The multi-filter combines the text filter and set filter, enabling more advanced filtering options. Agigrid supports tree shaking, allowing for the optimization of bundle size. The state of filters in Agigrid can be retrieved and manipulated. When dealing with large datasets, different row models such as server-side rendering and infinite row scrolling can be used. Additionally, the community edition of Agigrid allows for customization of cell values based on various criteria.
I'll select, deselect everything. If I type L-A-N-D, it's filtered this list, and I could manually select some of these if that's what I wanted. Or I can just click enter and it will dynamically select all those for me. That's the set filter. Again, there's a lot more you can do with the set filter programmatically and dynamically. But this is just to show you what is provided as a starting point.
And then the last one, which is arguably the most powerful filter is the multi-filter. And this mixes two types of filters. It provides the number filter. Sorry, the text filter, and a set filter. You can see this horizontal line here enables you to mix two filters. And check out edugrid.com, the documentation for what you can do. It can do a lot more than I'm demonstrating here. But here you can see a text filter and a set filter combined. So you could say, and this is not terribly useful with a date. With a number. Yeah, let's say it has six. That's not a great example. I'm gonna move this set filter to another field actually. I'm gonna use it on sports. I think that's more useful. There we go. So we wanted to contain the letter A. And just worth noting that whatever I type on the top will automatically reduce the bottom section. So if I typed X, for example, only boxing is now available. So it filters the selection below. So whatever you do on the top narrows down the selection on the bottom part. So if we did A, only sports with the letter A and it's gonna reduce our shown. And then before we could have something like 10 and it reduces further, I would apply the filter with an enter. So I know it's pretty brief on those two, the SID filter and the multi filter. They can do a huge amount out of the box without you having to write any custom code with a little bit of configuring. Out of the box, they do a huge amount as you've just seen, but with a little bit of configuration the Enterprise filters I've described, the SID filter and multi filter as well as the three free ones, the text, number and date ones can do a huge amount of functionality out of the box. I won't go through it here. I just wanted to show you what they were and how you could use them, but check out Agigrid.com for documentation how you can really make use of these powerful filters out the box.
So I'm gonna remove the Enterprise filters again. We're back to fully enterprise, sorry, fully community application. We're not using any Enterprise functionality here. Say you wanted to override a debounce, you wanted to slow down, you wanted users to have time to think before a filter was applied, you can add a debounce, or you can just compliment the filter in the first place. So to filter, like we saw before with the renderers, you can have cell renderer params, you can extend or compliment a filter with filter params. And as you'd imagine, if you've got a custom editor, which we're not gonna cover today, if you had a custom editor or a custom header, you can compliment it with header params or edits params. So in our case, we wanna change the debounce to be zero. So for this filter, which is age, we want the, to apply straight away, so there's no change, whatever I type it gets accessed on straight away. If you want to just slow it down, I can just change it two seconds. So now if I, whatever I type in there, it's gonna not respond for two seconds. So, I type 23, one, two, boink. So, whatever I type in there, now there, it waited for the debounce of 2000 milliseconds, which is two seconds before applying. There's a whole whole bunch of things you can use to extend the filters and I'll describe buttons in a second. But again, check out agigood.com for all the cool things you can do with a grid and the filter specifically.
Does Agigrid support tree shaking, Enterprise is around. Yes. So, yes it does. So, I won't go into this too much, but what we are using here for Agigrid community, Agigrid React and Agigrid Enterprise are all the functionality, everything that we include and some stuff will be tree shaken out. But if you really want to maximize or minimize, I should say your bundle size, then at Agigrid.com, go take a look at building and tooling and look at a packages versus modules. What we're using, yeah, with Agigrid Enterprise in the community are the packages and tree shaking is supported, but by default, we use all the code. Every single thing, even if you're using it or not will be here in the packages. If you want to reduce bundle size, then go take a look at the module documentation and in the modules, you only put in the module that you're interested in. For example, if you're using the core code, that'll be pulled in by default. But if you only want to look at CSV code and clipboard functionality, you'd only put in those two modules, and so automatically by default, your bundle will be reduced because you're not putting in all the code and code that's not being used. Yeah, so tree shaking is supported, but if you want to maximize the size or reduce the size of your bundle, go take a look at the Azure Grid documentation or packages versus modules, what the differences are and how you can use those.
Can you retrieve the state of filters for Azure Grid? Yes, and I will describe that in this section a little later on. So just wait for that. What about the date use case where you can't load all the data in one go? I do larger than the data. Absolutely. So what we're looking at, is that's something called client side data. The data we're using now, this application is called client side row data. All the data is pulled from wherever you want to pull it from and all the data is rendered. So all the data is in memory and only some of the data is rendered because of visualization. But still, if you had a million rows, you probably don't wanna pull a million rows into your browser. It'll probably kill your browser. So what you can do there is different types of row models. I won't touch on this in this section, but if you look at server side row data, you can get various options. So for the free version, you can look at infinite row scrolling. Take a look at the docs for that. I can't remember where that is on here. Infinite row model. So that's the free version. And this is something, I won't go into it, but infinite row model is something that you can use in the community edition for as the date implied, infinite row data. It gets chunks of data as you go. And then there's also enterprise row models which are more powerful like server-side rendering and viewport row model. I won't cover that here, but you have options in the community edition for that. Take the free version. So they can look at the infinite row model. And if you're in the enterprise version, you have even more ability. So you don't have to put in all your data at once and you can use pagination as another option. So take a look at that in azgrid.com. Row models and pagination are the way to go. The community edition on cell renderer, I know you can render different values based on the current cell. But what if you want to change the value on a cell based on the rates? Yes, absolutely. So yes, so I haven't got the code on the screen anymore, but remember you can have a cell renderer selector and that's called per row per cell and that passes down the API, the column API, the Grid API, the column definitions, the state of the grid and the cell value. So you have all the data, you have the entire state of the grid available to you as the cells been rendered, as the renderer is being chosen.
14. Using Renderers, Filters, and Buttons
Once you've chosen a renderer, you can determine what to show and how to show it based on the data. The default column definition can be used to apply properties to all columns, reducing boilerplate code. Buttons can be added to filters, but they won't apply until clicked. Apply applies the filter, clear clears the UI without applying the filter, cancel resets the UI to the current filter, and reset clears the UI and applies the filter. For more information on the buttons, visit agigrid.com.
Then once you've got a chosen renderer, you get the same data in your renderer and you can maybe display a red background if the data is negative and a green background if the data is positive. So at various stages you can determine what renderer to show and in within the renderer you can show what you showed depending on the data. So before the data is actually displayed, you've got a whole bunch of points in the Lifecycle to choose what's shown and how it's shown. I hope that makes sense. There was a lot there.
Okay, so I've answered those questions. So we're going back to where we were. So I've added a Debounce. Now say we wanted this Debounce of 2000 milliseconds to be applied to everything. We don't have to again, specify it on every column. We can supply it on the default column definition and that'll be applied to every field. So this that contains 2000, one, two. Now it filters. So again, anything that you can specify on a column, individually, you can specify on the default column depth and it'll be applied across all columns. So it'll reduce the amounts of boilerplate code you have to do or want to do. So let's remove that. We don't want to de-balance 2000 milliseconds in our case. The last thing I want to look at with filters here, except before we get to filter state, which is a previous question, are buttons, because I think they're quite useful. So let's go look at this again. We've got filter parameters back to age. And in this case, we want to do buttons. And these are four buttons. Practically speaking, you probably only want to show two buttons on a filter at a time. We're going to specify that on the age. So now you can see two buttons have appeared. And I'll describe the other two. These four buttons in total that we provide at the box. Now, the filter won't apply until the user clicks on something. So I can type 25 and de-balance is ignored. De-balance is ignored here. Even if you specified it, and nothing will happen until I click on Apply. And I can clear any current filters and then re-apply it. So just to repeat that, if I want to have 25, nothing happens until I click Apply. This is sometimes the result of what some users type in a whole bunch of things you don't want. There are groups to filter and un-filter as the users type in. Maybe you want the user to type some complex formula, or rejects, or something like that. Only for it to apply when you click Apply. When I click Clear, it will clear the whole filter UI, but not the current filter. So if you look at the background, you'll see a little filter, a funnel symbol, the filter symbol. So the filter is still in place, although we've cleared the UI with Clear. The cleared UI won't apply until we click Apply. So Apply applies whatever you've specified in the filter. Clear will clear it, but not apply it till you filter it again. So I hope that makes sense. Let's look at the other two buttons we've got here. We've got Cancel and we've got Reset. So again, just to remind you that this message you see here about Cars list, that's not an age-agreed issue. It's a hot reloading issue, so you can ignore that. So now you can see four buttons. Now, as I said earlier, you realistically wouldn't show all four buttons. You'd probably show two buttons. Probably Apply and Clear being the most common. So I've already described Apply. Nothing will happen until you click Apply. Clear will clear the current filter but not actually do apply that until you click Apply. Cancel will cancel back to What. So if I change this to be 29 and I click Cancel, it'll reset the UI back to 25 and not actually do anything. So do you notice, say for example, if I had some really long filter, let's say I did apply and I made a mistake and I was doing something else, and I thought, oh gosh, I don't know what I had before. I didn't mean to do that, you can click Cancel and that just resets the UI back to whatever the current filter is. So the current filter is A equals 25. And if I type that, and I don't wanna change the filter, I just wanna reset the UI back to what's the underlying filter, I can click Cancel. Reset is the last one, it'll clear the UI and apply it. So it's kind of like two buttons in one. Reset will be the same as clear and apply. Reset will do clear and apply in one go. So it clears it and applies it and there's no more filter. I hope that makes sense. Apply applies it, clear will clear the UI, but not apply it. Cancel will do any changes you've made and go back to what the current filter is if there is one and reset will clear the current UI and apply that. So it'll clear the current filter. That's a lot to take in with me just talking, but if you're not sure, if you want a reminder, go to agigrid.com and it describes the buttons more clearly than I probably have, I mean, how to use them. But again, realistically, you probably only have two buttons at a time, you wouldn't want to have four. But if you wanna see what the buttons do, check out agigrid.com. The point we have is to demonstrate that we provide four buttons out there in the box and 99% of times those four actions are the ones you'll want to use in your application.
15. Fixing the Day Filter and Completing the Filters
The Day filter was not working because it expected date objects in the row data, but we only had raw strings. By providing a comparator, we can convert the string to a date object and compare the values. Now all the filters are working: number, text, date, set, and multi-filter.
Okay, so let's remove these buttons and now let's go back to take a look at why, you remember, the Day filter's not working because the Day filter expects Days objects in the row data and we don't have dates in the row data, we'd actually got just raw strings. So what we're going to do is provide a comparator and I'm gonna copy this code so we don't have to type it, bit too much to type. Where is it? Oh, I can go to the GitHub. Here we go, so I'm copying this just cause it's a bit to type and if I typed it by hand I would probably make a mistake. So let's go take a look, hopefully I've done that correctly if this filter works. And I'll describe what I've done and why I've done it, I'll just check it works first. Now our filter is working. So before, if you remember, the date filter wasn't working because we expected date objects and in our case the underlying data is just a raw string. So what we've done here is to write a filter parameter and a comparator and this is useful if your underlying data is a complex object. Perhaps it's some weird data that you need to pass before you can do something with it in JavaScript. And the comparator allows you to do it. It gives you the value from the filter, which in this case is 24-08-2008 and the actual underlying cell value, whatever it is. In our case it's a string and so in this case we're gonna take the string and pass it to a date object and then we're gonna compare the date value. I'm not gonna spend too much time on this actual comparator. The point is that you can override what is compared by providing a comparator by filter params. So now we've got all the filters working. We've got a number filter, text filter, date filter and then I showed you the set filter and the multi-filter earlier. That closes the loop, I think, on all the filters. Thanks.
16. Using Server-Side Row Model and Filter States
You can use a server-side row model with virtualization, sorting, and filtering, but the responsibility falls on the developer to handle the data. The grid can't sort or filter data it doesn't know about, so the developer needs to listen to events and update the data accordingly. Inline editing can be achieved by setting the 'editable' property to true. You can also use a cell editor as a React component. To save and apply filter states, you can use a ref to store the filter model and the grid API's 'getFilterModel' and 'setFilterModel' methods.
Would virtualization, sorting, filtering, still work on a server-side model? Yes, but it pushes the responsibility onto you, the developer. So for example, if you're using a server-side row model but say your backend, your database has got a million rows in it and you're only pulling 1,000 rows in, the grid obviously can't sort or filter row data we don't know about. So what would happen there is that there would be a whole bunch of events. If a user clicks on sort or filter, we would call hooks or events that you as a developer would listen to and then update from the remote data source, the data. So for example, you were showing all rows from A to C and the user wants to show all rows from S to X, we would tell you that now that's what the user wants to do, you would get rows from S to X and return it back to the grid. So it pushes the responsibility from us at the moment and we can do all sorts of filtering and pagination, but if you've got server side data or virtualization or infinite scrolling, then you as a developer have to do those on your part because obviously the grid can't filter data it doesn't know about. Hopefully that makes sense. Take a look at the docs for real working examples. We've got whole repos, GitHub repos that show you how to do these there. Are we gonna cover inline editing with a community edition? Yes, so I can do that briefly. You can have fairly complex editors, which we're not gonna cover on this, but to make a field editable by default with just simple inline editing, all you have to do is say editable true. So by default, that's all you have to do, we're gonna do the age, now if we click on it, it's editable. So if I click on Michael Phelps, nothing happens, I'm clicking enter or double clicking, nothing's happening. If I click on age, it's now editable and I can change it to 29. So all I did there was set editable to be true. Editable can be callback as well, you can have it per row and per cell, you might want some cells and some rows to be editable and not, as before we'll pass down to you as a parameter, the state of the grid, the state of the cell, APIs and all that sort of thing, and you can dynamically determine what's editable. And then finally, you can have, cell editor and that can be a React component. Your React component, which we're not gonna describe today. But it could as we show it so with the red, editor, I'm sorry, the render earlier, and a filter which we'll describe next, you can have a cell renderer, I'm sorry, cell editor as a component. Hopefully that answers that question. So at the simplest use case, it just says editable, and then the cell will be editor, I assume that's what you mean by inline editing. Okay.
The next section we're gonna look at is filter states, which was a question we had before. So whenever you do a filter operation or sorting, or just about anything, you can get the states of the filter or the state of the filter, you might want to say a user's filtered on three columns in a specific way, and they want to save that. So every time that they opened up the application, it restores, you might wanna save the states, save it down to a backend. And when the user logs in again, load the states and return them. So let's describe how we can get the states and how would we can do with it. So, to save the states in our case, we're not gonna save it to a backend, we're gonna just use a ref for this. So relative to our profile. and we're gonna have, let's put this together so you can see the code. That's not far away from where we're using it. So, we've got a use refs that we can use to store data, and we're gonna have buttons that save and apply it. And these are gonna, we're gonna add the buttons in this section in a minute. So let's say, on button save, let's see how many mistakes I make while I'm live coding here. And I'll describe as I go line by line, what I've done. So we're gonna use this callback in a second, but what we do know is we're using the grid ref which we used earlier if you remember, on the grid component. Grid ref.current.api gives us the grid API instead of the post at the column API and recording get filter model. And that'll give us a straight and representation of all current models applied. But let's start off with that. Let's just take a look at that filter model. The on click, on button save, save filter. We're not actually saving anything yet, but we can look at the output. So reminder, we're going to get the current filter model and we're going to output to the console.log. So if we output that, you'll see, not very exciting. It's an empty object. Let's do something more interesting. Let's say age is equal to 25. And now if we outsave it again, we now see a adjacent object that's got age, the filter type is a number, the type is equal and filter is 25. Now you don't need to understand the output of get filter model or set filter model. You don't have to, the grid will provide what the current state is, you can save it and restore it. You can manipulate it if you want to, but typically you won't have to. And you don't have to understand it, but the point is this will output the current state of the filter. We can apply another filter and if we do a silver state again, we'll see that the adjacent objects is too age, with age and year. So we're not actually saving the filter, as is specified, we're just outputting it so you can see what the filter model is doing. So let's save that with, save filter dot current equals filter model. So on the ref we've provided above on currents, we're gonna save the current filter model. Let's have on button apply. And under this apply we're going to apply whatever's saved, and I'll just demonstrate how that works in practice. So we can have cons.filterModel equals saved. Again, I'll describe what I'm doing after I've done. ReddRef dot current dot API. So we're gonna call another API method on the grid, and I'm gonna go set filter model, filter model, and then we're gonna add a button to actually use this. So what we have here now is pushMe, which I will comment out just for simplicity so we don't see that. So we've got saved filter states, which every time I click it will save onto our grid ref, the state of the grid, and apply, we'll pull it off the current state of the filter and apply it. So let's try that out. Let's apply mitch on there and then country contains Australia. So we've got the current state is that, I meant to click on the filter, sorry. On the A, we've got anything that contains mitch, and then the country, anything that contains os. So we've got Australia and Austria and anything in an athlete name of mitch. So if we save that, let's say we go change the filter now. We go, we don't want mitch, we want tim and we want countries that have no, no, no country filter. Let's say we've got no country filter. So we change the filter. We've saved it earlier. We had, we had an athlete filter country filter. And now we've changed it, to only have athletes with the name of Tim. Now say the user wants to, he's made changes and thinks, okay, I want to get back to where I was before. We can apply the filter states. And now the filters are back to where they were before. We've got the athlete filter, which contains mitch and the country filter, which contains os. And just to recap what we did there, this was maybe a little bit quick. On the save button, we get access to the filter model, which is JSON data, and you can convert that into a string and maybe save it a database and then convert it back to JSON and restore it. But what we've done is, get the current state of the model and save it onto a ref in our use case. More realistically, you'd save it to a backend of our database. And then for apply, we do the reverse. We get the model that we saved onto the ref and we reapply it to the grid using the API and set filter model. That at a high level is, how you would get the state of the filters across the grid and how you'd reset them. You can manipulate that JSON data if you want to, most of the time you won't, but you can and then you can get it and set it using API methods. Before I move on, I hope that answers the, whoever had a question about filter states, I hope that answers your question. It's actually pretty easy.
QnA
Applying Filters and Using Floating Filters
The grid has undo and redo functionality. You can save states using events and roll them forward or backward. Floating filters can be enabled by setting filter to true. They appear for columns that have a filter. The filter menu can be clipped, but you can specify the popup parent to fix this. There is functionality called quick filters that allows you to externalize searching outside of the grid. Floating filters cannot be placed above the table headers by default. When viewing the grid on a mobile device, it's important to consider the design and show a truncated view with fewer columns.
I mean, api.getFilterModel will get this current state to the filters and getSetFilterModel will set it depending on what you want. Let's look at the questions here. And then, so we need to add, saveCallback. Well, for, I think if you're asking about editing, I'm not sure what you're referring to there, I'm afraid. Charles, when you say, so you need to add saveCallback, maybe you can ask again and expand a little bit about what you're asking there. I suppose it's the same if you have a few edited cell and so want to save all the changes in one action. Yes, so by default, the grid, when the user enters an editor cell with editables to be true and clicks enter, the underlying JSON data will be updated with whatever the user applies. You can listen to events and change that. So for example, if you're using something like Redux, you might not want to change the underlying data, but rather send it up to the Redux tool. You can listen to the save events and not save it down. Tell the grid, don't save the data in the editor and instead send it, fire it up for events or Redux and then it would fall the back down to the grid. So yes, you could. And depending on your use case, you probably would. I assume I can use this just to multiple states in history for undoing, absolutely. So the grid actually has undo and redo functionality. So you can always check out the grid, the documentation for how to do that. But if you wanted to do your own, perhaps it was very complicated, undo and redo, yes, absolutely. For each edit operation or each filter operation, you could save the states using the events. You'd listen to the events, save the state of events to wherever you want to save it. And then you could roll those forward or backward depending on what the user was doing in the grid, yes. We've just shown filter state here, but you can get sourcing states and all sorts of states. The most common are edit filter states, grid states and data states and filter states, but using events you could capture anything and apply that as your state. Okay, I hope that makes sense. So let's move on. So next we'll look at applying filter. Well, actually one other thing I can do here. So we can add, say you wanted to clear the states, you could on button. So yeah, I'm gonna save this. We don't need a filter model in this case, I'll just write it and I'll describe what I've done. So, I mean, it doesn't really matter in this case, but. Yeah, so here we go. We've got Save, Apply and Clear. So Save does as we've done before, let's say that we've got 25 and, oops, not athlete, that's Mitch. So what am I filtering on there? How do you add this? Sorry, I made a mistake. Contains Mitch. So the user's done some filtering and you then he's done some filtering or she's done some filtering and you want to provide a functionality where you just reset all filter states or sortable states or so on, you can clear it and this applies to all the states, filter state and sorting states. You can apply an empty model, which is just an empty object and that would remove any sorting or filtering that had been applied. Just a useful trick that's occasionally useful. So the next thing I want to move on to is floating filters, which are pretty useful. So if you want to have a floating filter, all you need to do is filter true and that will enable this. So this will enable a floating filter will enable the floating filter, as you see here across all filters where there is a filter. So what I mean by that is if I move floating filter to my default column there, I remember default column there applies to all columns. You'll see that all of them have filters. That's because we've set filter to be true. I'll remove that and refresh. So now I've removed, just to remind you, just to show you what I did there, cause it was pretty quick, we had defaults filter true in the default column there, which means that every column had a filter, but to demonstrate what I'm talking about here, I removed that, and only the column that have a filter field, the date, age and athlete have filters. So that means that only athletes age and date can have floating filters. Although floating filter is enabled in every column, it will only appear for columns that a filter appears or is present. And you can do the same thing inline that you could do with the actual filters. So for example, I could do Mitch, I could do 25, and whatever you do in the floating filter is reflected in the actual filter above. And all we had to do there was add floating filter be true. So I think this is a pretty useful piece of functionality, and most of the times all you'll have to do is place five floating filters equal to true, and out of the box, you'll get some pretty cool functionality for the user. So the user doesn't have to click on there and do stuff. You could simply or she could simply do it inline. What else did I want to talk about there? Okay. The last thing I wanted to talk about on filters is clipping. So occasionally, depending on your application and depending on where you're seeing it, you come across a case where the filter might be clipped. So in this case, we're changing the height of the grid or the parent grid to be 300 pixels. And that looks fine. But if we look at, if we use something like set filter, and I'm only showing, you're showing the set filter for demonstration purposes. If we look at the, and we remove floating filter. So what I'm trying to describe here is, you'll see sometimes that the filter menu, the menu can be clipped, hang on, what have I done? Okay. So I'm going to set the default filter, which would be a set filter. Don't worry about the filter I'm using here, that's not what I'm trying to demonstrate. So I need that to be even smaller. Let's do 150. There we go. So as you can see, the filter menu is being clipped because the grid only has 150 pixels to play with. It's being clipped at the heights of the containing parent div. And this can happen if you're on a mobile device or the user shrinks the browser to be very small and what you can do to fix that is by default the popup parents or what we call the popup parents will be the parent div. But in a use case like this where your grid's pretty narrow and pretty small and you still want to show the full context menu or grid menu and filter menu, you can specify popup parents. And this is used for specifically for parent filters. But its useful in other places as well, like context menu. So I've said document body to be the popup parents and you'll see now that the popup is showing fully and breaking out of the parent div. It's a small little thing, I just wanted to highlight because it can be a phasing, it can be a gotcha. And all you need to do is specify the popup parent. By default you probably want to use document parents but you may wanna use some other elements. I hope that makes sense, if you see a clipping on your menus take a look at pop up parents and you probably want to set it to be document.body by default if you've got very narrow or very thin grids. Could you specifically take a look at the questions? Patricia's asked, could you have a top higher level search outside the grid table? Yes, there's a thing called a quick-search, quick filter and a quick filter allows you to externalize filtering. So hopefully you can see my browser here, I've got a little TextBox out here and I can do a search outside the box and this could do more than what I'm showing here but there is functionality called quick filters so take a look at that under the documentation and that allows you to externalize your searching outside of the grid. Can you place the floating filters above the table headers? No, you cannot by default but you could create, so if you if you needed to perhaps your UI designs and specify that, you know floating filter had to be on the top and it is at the bottom, you could create a custom header, it'll probably be a fair bit of work but you could create a custom React components that does that for you but out the box no, floating filters are as far as I remember, below the actual headers. With this filter pop up to full screen on a mobile device how does the grid look on mobile? So the yes, yes, that would work on mobile device but you need to be careful with having tabular data on a browser, on a mobile device and this is not just a degree, this is any tabular data. You probably don't want to show this sort of thing on a let me show you back to three, 500 on a mobile device. You probably don't want to show many columns like we've got here and many thousands of rows as we've got here on a mobile device. You'd probably want to show a truncated view and fewer columns. So this becomes more of a design thing. So something you'd probably want to talk to you with your UX team or if you're the UX team have to think about. You can show tabular data and that is useful but you don't want to show many columns and many rows because although the user can scroll and that's probably okay on a tablet on an actual mobile device, yes, you can show it and yes, the menu will be, if you filter, it'll be shown. It probably wouldn't be a great UI experience. So smaller grids and then consider a different design of this decision on small devices.
Creating a Custom Filter Component
We're going to create a custom filter component in React for Agigrid. The filter component will have four mandatory methods: isFilterActive, doesFilterPass, getModel, and setModel. For this example, we will focus on isFilterActive and doesFilterPass. We will check if the filter is active based on the filter state, and if it is active, we will apply the filter per row. We will create a year filter with two radio buttons, on and off. Clicking on the on button will set the filter state to on, and clicking on the off button will set the filter state to off. We will then apply the filter to the grid and observe the results in the browser. The filter will be active if the filter state is not equal to off, and the filter will pass if the year value is equal to 2008. We will also implement the filterChangedCallback method to notify the grid of any changes in the filter state.
Tablets are okay but on mobile phones, less rows and columns is probably what you want to do because it's such a pain to have to show through many rows on a mobile device. But yes, this is the answer. It will work. It works just fine on a mobile device. It's more of a design question at that point.
Okay, what were we gonna look at next? Okay, so the last thing we're gonna look at today coming up to two hours, it's about, this workshop was planned right when it about two hours. So we're gonna overrun it a little bit. If you have to go, that's fine. You can take a look at the GitHub repo and I think this has been recorded, so you can look at the recording afterwards if you want to track. But the last thing we're gonna look at is custom filters. So we've looked at what Agigrid provides out the box, three free ones in community and then two additional ones in the enterprise. A total of five if you use an enterprise. But if those don't work for you, and again, I'll look at agigrid.com for full documentation about what the filters can do. But if you want to do something special or something bespoke, like we did with renderers, you can have a custom filter.
So the first thing we're going to do is we're gonna create a new file and we're gonna call it yearfilter. Yes, Mohammed, I'll share the link in a minute, that's fine. Filter.js. Let me just share that link quickly. There you go. And just if you've joined late, just a reminder that each section is a different branch. So you can see the code for that particular branch if you click on it. There's a number five custom filters at the moment. So, I'm not going to attempt to write out this. I'm going to copy it and then I'll go through it and describe what we're doing. So, like we did before with the, like we did before, we're gonna have a custom React components, like we did with the renderers, but this time, we're gonna have a little bit more of a complicated components and this time we're gonna do it for filters. So, there's two ways to create components at the moment in React. You can add functional components, like a hook, which we're gonna demonstrate here, or class-based components. If you're using a functional component, there are some life cycle methods that the grid needs to be able to call for filters to work and editors, as it happens, and other things. And to expose those to an external user, you need to use a forward ref and a use-imperative handle. I'm not going to go into too much about how these work. Again, that's a React-specific topic, so go take a look at the React documentation if you want to know. But in a nutshell, these methods here that I've highlighted, isFilterActive, doesFilterPass, getModel, and so on, those are filter-specific life cycle methods that the grid needs to be able to call on the component. And for the grid to be able to see those, or for any components to be able to see these methods, you need to expose them via a use-imperative handle. If you're using a class-based component, you don't need to use forward ref and use-imperative handle. The methods will just be just exposed by default. I hope that makes sense, but in a nutshell, any methods that you want to expose to the grid have to be within use-imperative handle. Everything else not in use-imperative handle is effectively invisible to the grid. And that's good for encapsulation and so on. So when you're writing a custom filter, you need to provide a minimum of four methods. isFilterActive, doesFilterPass, getModel, and setModel. For the first pass, we're going to ignore getModel and setModel. So we're going to return undefinable model and do nothing with setModels. So we can ignore those for now. We still need to provide them, but the grid will call them when things happen. But we're not going to do anything with them for now. What we are going to look at for this filter is is the filter active? And if a filter is active, that the grid will per column see which filters are active, and if they're active per row, apply that filter. So for this one, a year filter, we're going to check if this filterState is not equal to off. So if by default the filterState value is off, and if it's off, the filter is off. If the filter is any value other than filterState, so in other words if it's a year, it'll call this filter pass per row. So per row, in our particular case, we've hard coded it, and we're going to check out the year value, and if it's 2008, it's going to work. So, in our filter we've created two inputs, so a radio button, and the filter's either going to be on, or it's going to be off. And if the user clicks off, the filterState will be off. If the user clicks on, the filterState will be on. Remember, we've got a simple filter where the value is simply hardcoded, and it's hardcoded because I just want to talk about the params or props that happens here. And we have two listeners for those buttons. One will set filterState, and one will set filterState on, and one will set filterState off, so we've got a filter, but we're not doing anything with it. Let's go import it. I'll remove Enterprise, we don't need that for now. And I'll remove the other filters for simplicity. So, import, we've imported the year filter, and we're gonna apply it here. So remember before to use the default filter, we'd say true, sorry, true, or to use one of the provided ones. You could use AG text column filter, for example, and then if you pass in a React component, it'll use that React component. So let's save that, and go take a look at our app. If we refresh that just to make sure. So, here in the browser, you can see the results of our year filter here. We've got the two buttons, on and off. By default it's off. And then, by default, the filter isn't active. You can tell the filter's active because there's no little filter symbol here. We click on on, you'll see that the row's filtered. You can see that the little funnel symbol appeared because is filter active will be true because the filter state is not equal to auth. And the filter applied. We missed one step, apologies. The filter only applied because of this line I've highlighted in the browser, in the IDE. So on the props part of the filter, there's a method called filterChangedCallback, and that's passed to this prop because it's a filter. It wouldn't be passed to an editor or a renderer, for example, but the grid knows that this is a filter and provides this callback, filter callback. So in this effect, every time the filter state changes, in other words, if we turn it on or off, we call back to the grid. We're effectively telling the grid, hey, the filter's changed, please act on that. So every time we change the filter states, we call filterChangedCallback on the props, and the grid will call, is the filter active? And if it's active, doesFilterPass per row?
Enhancing Custom Filters: From Basic to Generic
We've created a generic filter component that can be used for multiple columns. The filter component has four mandatory methods: filterActive, doesFilterPass, getModel, and setModel. We've discussed the parameters available in the filter methods, including the row data and the column field. We've also externalized the filter text and criteria, making the filter more generic. Additionally, we've added radio buttons to the filter for more advanced filtering options. The filter component is now capable of filtering rows based on the selected criteria.
Hopefully that'll make sense. So just to recap, we've got four methods here. They're mandatory. The ones you have to implement, by default, for a filter to be useful is filter active and doesFilterPass. GetModel and setModel are mandatory, but you don't have to implement them. It doesn't mean, though, that you wouldn't be able to restore filter states, custom filter states, or set custom filter states if you wanted to, like we did earlier. And we're going to do later.
So that's our bare minimum filter. Now, I've hardcoded this because I wanted to just talk about what you get in the params. You could equally call this props. So you'll see that I saved it and output per row because the filter is active. Per, if the filter wasn't active, the doesFilterPass wouldn't get called. Per row, it outputs the row node, which is an internal node. It's occasionally useful, which we're not going to cover now. But then you also get the row data. So each of these rows, per row, we call doesFilterPass, and we provide the whole row data. So for example, if you wanted to do a custom filter that actually looked at three or four columns at the same time, you'll have access to the whole row, not just the cell value, you've got the whole row. So params.data is the row data. And what we're doing in this particular case is for that row data, we're looking at the year value. If it's 2008, we want to have it filtered. So I hope that makes sense. Still, this is not a very useful filter. We only filter in by 2008 based on a radio button. So let's see if we can make this a bit more useful. Um, okay, so let's make it more useful by changing the filter text. So we've got here at the moment, we've got year filter. So at the moment, we can only, no matter what column we put this on, it'll say year filter. Let's say we want to make that a bit more generic. We can make this filter a little bit more generic. And as we saw earlier, like we did with the default params, you can extend them, and we can pass in anything here. We don't, the grid doesn't do anything with these props. We simply make it available to the renderer. So then we can say filter text. And in this case, we're gonna say, year filter. So in the end, we'll put an exclamation mark at the end just to show that it's different. So on the props, we'll be filter text, and we're gonna use it. What did I? Props. Props.filterText. So if we do a refresh and we go look at year, we can see year filter with an exclamation mark. So it's very similar to what we had before, but we have changed it. So we no longer hard code with in the grid year filter. We've externalised that, and we've got year filter with an exclamation mark. So that's step one into making this more of a generic thing. Step two is we're only filtering by year. But we can actually filter by the column that's specified at the props time. So let's do that in the filter first and then I'll describe what we're doing in the...
So we can say const field. So one of the values passed to the props is the coldef, and that's the column definition that's specified. And we can extract the field. So if we go look at here, each time the filter is called, this is made available on coldef, the field of the filter, filter params. But the one that we're particularly interested in is this field year. And that's made available to us via the props and we can extract that. So we can say that we want to filter field to be 2008. So this is gonna still, this is gonna have the same effect as what we had before. We're gonna say whenever the year is 2008, filter that row. That has the same effect, because if you remember the field is year. So field params.data field is the same in this case as params.data.year equal to 2008. And if we go back here, it all works. But still, it's generic. We haven't had to hard code the value. Sorry, the field that we're gonna use. But obviously 2008 is still hard coded. So let's see if we can make that a bit more generic. And let's call this props.criteria. You can probably see where this is gonna go. Now 2000, criteria is 2008. And this would work the same hopefully as before. We still filter in by 2008, but again, we've externalized it from our filter component, so everything in here is generic now. Nothing in this component is specific to the year column. We could use it to other columns, which we will in a second. But we've externalized everything, so we've passed what's year specific in filter params, and then in our generic filter, we can extract the filter text, and the criteria. Let's take this one step further. And let's say that we want to show radio buttons. So, sorry, I'm just refreshing my notes here. I'm going to copy this, because I'll probably make a typo. Again, I'm going to the GitHub link, and values. And I'll describe what I've done. I'm taking this only a little bit further. Although, I've copied all the code. As before, generic field. We're going to look at that. And now we're going to output a list of values instead of just one value. And in the app, we're going to have off. So I'll just make sure that works and then I'll describe what I've done to close the loop. So now we've got off, we're going to filter, I'll put it on here, instead of. Let's do, whoops. Maybe not. 2004, 2006, 2008. So we've got the off states, we can apply filters on radio buttons now. So we've made this a little bit more generic based on radio buttons.
Custom Filter State Handling
We've made the filter more generic by using radio buttons. The filter can now be applied to any column, such as age filter, year filter with different values. The state and filter values are externalized, allowing for a generic filter. The filter state is determined by the selected button value. The code for this custom filter is available on GitHub. We've also discussed the recording availability of the workshop and the use of state in custom filters. When editing grid data, the underlying row data will change by default. To keep the grid state in sync with the data source, you can listen to edit events and update the data source accordingly. Documentation and examples are available on GitHub. Lastly, we've explored exposing methods in custom grid components and demonstrated the use of a special filter action button.
So we've made this a little bit more generic based on radio buttons. And I'll describe again what I've done in a second. So because it seems like a lot, but now we can take this, although it's still called year filter, we can apply it to any column and now we're going to have age filter, year filter, 18 and say 25. So because we externalize stats, we can have, we've got a generic filter now. Let me go describe what I've done here.
The only differences, so as we said before, we made this a generic filter. So we will filter based on the current, the column that's specified in the column definitions. We've made the title, and externalized, and we provide a list of values on the column definition. And we output those values as buttons. And depending on the button, filter state will be set. So, in this case we have 18, 25, or off. And in here we've got 24, 26, 28. So that's very specific. All that information is very specific to this custom filter that I made. You're unlikely to make a filter that's specific. Or, sorry, this, like this. But what I'm trying to demonstrate here is these two methods and how they work, and how you can complement filters with filter params. Remember the grid doesn't do anything special with the params you parse here. Unless they're something that's specific to a grid, to one of our filters, title and values will simply make available onto the props of whatever component you're specifying. Let me look at the questions.
Okay, I'm, Mohammed, I'll provide the link again. Hopefully you can see it this time. And, Charles, yes, I believe so. That's probably a question for the hosts of the workshops. It is being recorded, so I assume it'll be made available post-workshop. That's not a question I can answer. I think it is being recorded, so it'll definitely be made available. How it's being made available, I'm not sure. Perhaps ask the event organizers. But at the very least, the code that I've gone through will be available on GitHub. So the last thing we're gonna look at is state, because this is quite useful if you're having a custom filter. Take a sneaky sip of water. So, in this filter, we're going to return, it needs to be an object, well, it needs to be anything actually, because when the set model is called, it's gonna be whatever you've provided. So that doesn't have to be in the format that our filter's used, this can be anything. So let me demonstrate this, because the filter you say, this filter components, whatever we say, this filter component will need to understand. So it kind of goes hand in hand. So if the filter states equals of, return, undefined. So there is no filter state if the filter is off. Otherwise, return, state, filter state. So this may look a bit like certain states in React components, it's not, this could be called anything. This is just, whatever we save here, whatever we call here with the model will be called later on in set model via model. So we just called it in a state in our use case, but whatever you saved and returned to the grid and this is entirely up to you and entirely domain specific. And then on the set model, we do, if the model is null, set filter states off. Else, set filter states, model.state. So what we've done here is that, if there is no filter set, the model will be null and we'll set filter state to be off, which again, just remind you, the filter state is off, the filter is not active. If a user's done some changes and you decide to save the state, the filter state will be saved and when you call set filter state, restore the filter state, whatever you've saved yet will be passed to the model. So in our case, if we've called with 2008 as a value, state 2008 will be passed down and we'll pass that to set filter state. That's specific to a custom filter, but the code that we can use to test this is the same as we've done with any filter. So if you remember earlier, we had the save button, and the apply button, and a clear button. We can use those buttons as we've done before, even though we're gonna use a custom filter. So let's go back to our app. Let's refresh it. So let's look at our custom filter. We're gonna fold it by 2004 and 18. And now if we save that, that custom state including any out of the box filter state will be saved. We can go do something else now. Let's clear that and clear this one. And then we could restore the state again by apply. So what we've done there is we've called get model on each custom filter and any out of the box filters but you don't need to worry about that, we've called get model when we call get filter states, get model is called on each bespoke or each custom filter. And when reset model state, a filter state is called, set model will be called on every filter. So this is done for you for free in the defaults filters provided by AgGrid, but if you're doing your own custom filter, it's very simple to implement the model, the get model and set filter. And this is probably as complex as it would need to be. But again, the state the model you save and restore can be as simple as as complex as you need it to be. So whatever you return here and is passed to you here is entirely domain specific. When a cell is editable, how do you make sure that the data source and the grid state in sync without re-rendering? How, who would own the grid state, row data or Olympic winners? So when the data is read from Olympic winners dot JSON, so the JSON file is immutable, the grid can't obviously change that, but the row data is mutable. And if by default, if you edit grid data, the underlying row data will change. If you don't want that, if you want your golden source of data to be Redux for example, I'm just using that as an example, you could listen to events on edits and capture those events, prevent the event being saved down and instead fire it up as an event, a change event to the Redux and then flow back down to the grid. So you can always still, you could still have a single flow of data from Redux down. We do have documentation and working examples on repo on GitHub on how to do that. So check out azgrid.com for docs on how to do that, and that'll point you to repos for how to do that. But by default, the road data that we use in the grid is mutable. So this data here is mutable. And if you didn't want that to be the case, we document on how to do that. I hope that makes sense. So the final thing I was going to look at, oh, so this is true of any custom components. I'm going to describe what on how to do it on a filter component but this, what I'm going to describe now could be on any custom grid components, editor, filter, header components, filter components, you have certain use cases where you on a component, you might want to expose some method and be able to interact with that method. So you've got, let's expose my special filter action. And we'll do that, my special filter action. And again, for this to be visible to the grid or anything else you need to, in a hook, you need to use in pairs of handle. If you're using a class based components, you don't need to do that. But in a nutshell, you need to use, whatever you pass in here will be exposed to the grid. So, this isn't good specific. This is something entirely domain specific. You might want to fire off an event or change the color or something based on some external button. So we've exposed this, but we're not doing anything to it. There's a new button. Let's use this push me button, which we defined earlier. And let's use that. So we're gonna use the grid API. Grif.current.API.GetFilterInstance.
Exposing Methods and Enterprise Features
You can expose certain methods in custom React components that you put in the grid. By using the getFilterInstance method, you can access the filter instances and perform actions on them. The useImperativeHandle hook allows you to expose custom functionality in your components. The getFilterStage method can be used to call the exposed methods on the filter. Another method, getModelAsString, converts the filter state into a string format. This is useful when using the floating filter in conjunction with a custom filter. Only row grouping, set filter, and multi-filter are enterprise-specific features in Agigrid. Everything else is available in the free Community Edition.
Yeah, and then we're gonna call back. I'll describe what I've been here. So, I'll just test it, and then I'll walk you through what I've done. Push Me. So, my SpecialFilter. As you can see down at the top I clicked Push Me. And then the special Bespoke method that we exposed on the filter can be called. So, what this is demonstrating is that when you've got a custom React component that you're gonna put in the grid, you can expose certain methods if you want to. Not mandatory, just an optional thing. And what you expose can then be called. You firstly, you can get hold of the filter instances like this, get filter instance. You pass in the column you're interested in, that's the key. In this case, we're gonna call it on year. Asynchronously, the instance will be returned to you of the column filter in place. And then you can do stuff on that method. You can do some, whatever you expose. In our case, we're exposing my special filter action. This is not common, but it is useful occasionally to do something. So you might have externalized buttons and you may want to do special things on your filter or your editors or renders to change color or set default or something. Either way, you can access the pure custom components by exposing them in use imperative handle. And then you can call them by using, get filter stage. And then you've got, get editor status and so on, get editor instance and header instance. You've got all sorts of things. That's just a way to add custom functionality and be able to call that on your grid. Sorry, on your components.
The last thing I'm going to describe and the last thing that we'll touch on today was another method. So what we described here earlier was the four mandatory filter methods you have to provide. They are others. There's about four or five others. I won't go into them, but what I will describe here is get model as string. And what this allows you to do is in string format convert whatever your filter state is into a string format. So for example, if you had a filter that had a spinning dial and you couldn't really show that in a floating filter, perhaps you want to do a set. You have the filter as a spinning wheel and then whatever value is chosen in the floating filter you want it to just show a simple value. How you would do that is you implement to get model as string, return whatever the model is as a string. So if filter states equals off return an empty string, otherwise return the filter states. And then if we go to the column, we can say floating filter true. We don't have filter so let's set it to 2004, 2006, 2008. At the moment we've got it echoing exactly what the filter is, because these are simple values. But let's say that the value you're saving your filter is actually quite a complex domain specific value and you want to reduce it to a simple string value. You could have something like my filter value, that's probably too long. And then you can see it says, filter value 2004. So if you had a complex value in the filter that doesn't make sense to render in this floating filter, you can reduce it to a simple string and change it into a filter. So that just to remind you, that get model a string and that's most useful when you're going to use this floating filter in conjunction with a custom filter.
That's, that's all I had covered. All I wanted to cover for today. But we've overrun a bit so by about 25 minutes, it's not too bad. I'll wait around on this and I'll check out this call now just to see if there's any question there. No questions on this call. I think probably a few people had issues maybe joining this call. But hopefully I'll wait around for another five minutes. If you guys or girls or just people generally want to ask questions, I'll stay around for another five minutes. But if you've got any other questions, Stack Overflow is a great place. We keep an eye on that. And we actively answer things, check out our docs for all the things. And we've touched barely 5% of the good functionality. So please feel free to take a look at Stack Overflow. You can use GitHub for legitimate issues. Please don't use that for questions. Rather you Stack Overflow. If you're interested in acquiring a license or trying out Agigrid, try contact email info at agigrid.com. Remember enterprise is free to trial. And if you don't want to console message or watermark, you can get a free trial key. Thanks everyone for joining. I really appreciate it. Really good turnout, great questions. I'll stay around it's 25 past for me. I'll wait around for half past for any questions. Otherwise, thanks very much. It was great to be a part of this. I've got one question coming I think from Bruna. Thanks everyone for your thank yous it's appreciated. Yeah, so. The only thing I've shown you today that's enterprise specific is row grouping and set filter and multi filter. They're the ones that you buy out of the box. Only those three things. Set filter, multi filter, and row grouping are the only things I've described in this talk that are enterprise specific. Everything else is in the Community Edition and free to use. So the custom components, the renderer or the filter, those are entirely free to use. The states, everything else is free. There's only three things that I've gone through in this call. There's a ton of enterprise functionality. Please take a look at edugood.com for more, but specifically for this workshop, set filter, multi filter, and row grouping were the only things that covered that were enterprise. Everything else is available in the free Community Edition. Three more minutes, some more questions. Thanks Michael. Thanks Michael. So if you're using so if you're using use state the whole IRU won't so let me step back a second. The answer is it depends. So if you change in a cell value in the grid. So if you just click on edits, editable to be true.
Grid Re-rendering and Data Changes
The grid only re-renders the edited cell, not the entire grid. When changing all the row data, only the affected rows are re-rendered. The same applies when using Redux. The grid only re-renders the changed row data. It's important to consider your use case to avoid unnecessary grid re-rendering.
Let me demonstrate this. So let's say that country and make country editable. And if we go to the browser. I would do X. The whole grid, so the cell value and the underlying used row data change, but not the whole grid. The whole grid won't re-render, only that value, that only that cell component will re-render. If you changed all the row data, the grid itself, the component itself doesn't re-render, but we will re-render rows. So if you change all the rows, so if you're using a row model where you scroll down and you're putting, and you're re-rendering 10,000, say 1000 new rows, of course, the old rows will be destroyed and the new rows will be rendered, but if you're doing new states and like, like I've demonstrated, yeah, the whole grid doesn't get re-rendered. Only the cell that you've edited gets re-rendered. And the same is true if you're using redux. If you falter down, and the use, the grid row data change, the whole grid doesn't necessarily get re-rendered. Only the row data that's changed gets re-rendered. It's a slightly complicated question because it depends on your use case. But as a rule, you shouldn't have the grid re-rendering when data changes.
Comments