So, 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 different sections of this talk. As we go, I'm going to be coding live as we go. If you feel that you've 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'll describe the code as we go. So, for example, in the first section, here's the code for the first thing they'll introduce as I discussed, 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 go off to the workshop, take your time, 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. We're just going to call it hello. Keep an eye on the Discord channel. So, we're just creating a simple boilerplate
react application here. There's nothing to do with the grid so far. Just installing all the dependencies. It's taking its time, I'm sorry. Wow, that took longer than I thought. Sorry, guys. I'm good. Okay. So, if we go to hello, we'll see a normal project. I'm going to 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 going to save it and save the dependencies. The first one we're going to install is AG grid
community. And AG grid
community has all the core features and all the free features. You're able to use the features in AG grid
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're also going to install AG grid
react. And AG grid
react is the
react rendering side of things. So, you need the two together. The AG grid
community is the core grid code. And that's part of the
community edition. And AG grid
react, you'll need as well for
react integration. And that provides the
react rendering. We'll install those dependencies. That was pretty quick. We'll go to IDE. Yay. Available. 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. Okay. I don't see any 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 to answer it. Okay. So, we started off with what
react create app is 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 if someone lost. 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 again. Okay. So, that's what create
react app has given us. So, the first thing we need to do is install our AG grid
react component. We'll pull it in. We'll get rid of the stuff in there which we don't need. And we'll use our AG
react component. So, so far, this won't do anything for us. At the minimum, a grid or a 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 add some local
data to take a look at what that might look like. So, each of these fields will be something that we can pull out and view in the grid. Row
data is just a array of JSON
data. You can have as many properties as you like in it and 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 the grid of this functionality for you to read that type and display it however you wish. So, in this case, we're putting some local
data in the later section and we're going to show you how we can more realistically pull this from a remote source. So, that's our row
data. We haven't done anything with it yet. So, that will tell the grid to display that row
data. That's only half the story there because we also need to choose which columns to pull out. So, your row
data can have hundreds of fields and maybe you only want to show one or two. How you pick out what
data to show is with the column
data. So, let's do that next. And like row
data, this is an array of JSON
data and at a minimum, you need to specify the field you're going to show. So, 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. I'll pause in a second and tell you what the agenda is. Okay. So, that looks all messed up and that's fine because we'll get to that in a minute. So, I'll pause for a second and discuss the agenda. I mentioned it briefly, but for those that have joined afterwards, I'm going to be describing some of the basic functionality provided by the grid. Sorting, 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, we'll describe how you get a license, how you can trial it, and briefly some of the
enterprise features. But the bulk of the talk of this workshop will be free to use
community features. And just basic stuff, really, gets you up and running 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 joined later. These are GitHub repo. And each of the five sections here is on the repo. And I'll show you the code for that particular section. So, 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 answered that question, Clint. So, so far, we've installed the AgieGrid
community and
react dependency. We've 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 pull in some
css. And the thing that you want
css dependency, you absolutely have to put in is the structural AgieGrid
css. And that is from AgieGrid
community, just styles, AgieGrid
css. So, at a minimum, you need to provide this. Why is that not working? Oh, yes. I've got to provide a class name. I'll tell you why I'm doing this in a second. And the heights. So, normally, you wouldn't hard code the height here. But just to play purposes. And I'll describe why. There we go. So, this isn't important for this particular section. We'll come back to the intersection. So, can we specify the heights? The grid will fill the parent's div. So, in this case, we've got a simple div and we set the height to be 500 pixels. In a real app, you'd probably have this as part of a larger application. But regardless, the AgieGrid components here will fill whatever parent div you've given us. So, in this case, we've said it's 500 pixels wide. And just to remind you, we've pulled in the bare minimum, which is AgieGrid
css. And this provides the structural
css that the grid needs. So, in the grid, in the browser, we can see the three columns and rows. We can see make, model, and price, which we've specified for the column definitions. And we can see the row
data for 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 pull 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 pull in at a 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 AgieGrid reacts styles. We provide a handful of styles. And we can 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, Agie's theme Alpine. And now you can see the grid has got some styling. It's got rows, it's got the bolder fill 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, balance 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 styling pulled in. You need row
data and column divs. And in almost no time at all, taking away my explanation, you'd be up and running with a simple hard-coded 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 column
data will probably be hard-coded. 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 the grid or in 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 going to use states. Ah. And we need to do that so that we can asynchronously set the row
data later on. Let's pull that in from
react. So we've... What have I done wrong? Okay. This is the hazard of live creating, I suppose. Everyone watching probably failed to get the monitor of 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 better. Is that clearer, Samuel? Please let me know. I'll zoom in further if it'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, 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. So when the hook's rendered for the first time, we'll want to... So I'll pause you for a second. When you deploy your app for real, this will just work. But as we want to get this
data from a remote source, which has HTTPS and we run in locally here, 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're going to read from. I'm going to 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 just go to the
data file and save that under public and we'll call it OlympicWinners. Now this is only necessary to get around some cause issues. 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 file and slash OlympicWinners.json and then we need to get that array
data and tell it to Jason. Jason is what it is and finally we want to set 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 going to use Olympic
data, which is a bit more and I don't want to type these out. So I'm just going to 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 got to make sure it's all working. So let's go see if I've made any typos. Yay, I have made any typos. Okay, so I did a few things there and you were watching me type. So what I did firstly is save that OlympicWinners.json from a remote source locally and that's just because if we're running localhost, 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 row
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 similar, it's realistic
data, we've got loads of rows and a few columns. So we've got athletes, 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're writing a grid or implementing 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. But let's take this a little bit further. Your users will probably want to, at the very least, sort and filter their 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 could 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 note we can sort by up and to including dates for 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 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 def. Whatever we specify here will be specified across every column that you have default. Column, let me make sure I spell this correctly. Default call def equals memo. So just to pause you for a sec, I'm using use 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 while we're using it in Grid and I'm happy to field it. But these are standard
react things and I probably won't go into too much detail about why we're doing something or the other with this particular
react feature. We're going to return an object and we're going to have sortable, true, filter, true. And we're going to tell the Grid to use this. Okay. So now we should have sortable, filterable, and every column. So every column now has sortable and filterable. So you don't have to repeat yourself over and over again. And this is, so to describe two property attributes, you can do sortable, filterable, sortable, filter, sorry. 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 that I actually import, yeah. But let's say you wanted to override it. You wanted to override a 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 a locally will override. So this one doesn't have filter now. It's still got sort because we haven't overridden that, but the filter is gone because we've overridden 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 from 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 the score. If you can ping here, I'll answer questions as I can on the Zoom channel. Don't worry about the score if you can't reach there. OK, so far so good. Let's say now we want to act on some events. 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. But we've said for sorting and filtering. Let's take a look next at events. Say we want to do when a user clicks on a column, we want something to happen. Perhaps they click on something and we want to show up. Say perhaps they're looking at a whole bunch of shopping items and they click on something and we pop up with an image to show what a certain 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, 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 Bruno 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. Let's say we've only seen 15 rows there. I'm not sure how many rows we've seen. But say we've 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. So I 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 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 about this? Yeah. Animate rows. True. I need to refresh, I think. Okay. That's refreshed. So the hot loading is great, but it doesn't always fully refresh. So hopefully you can see before now that there's a vote 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 multiple. And now we can select rows by holding down command or shift. And what I'm trying to demonstrate there is we talked about column properties, sortable and 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 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 a property. So much of the grid functionality is unlocked just by enabling setting to 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 a better way to do it, especially in
react, is to use a ref. So we'll say grid ref. I'm doing a little bit backwards here. So we're saying we're going to pass down a grid ref. We haven't actually specified it. So const grid ref equals use 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. And now this will be set when the grid's rendered. We'll be actually going to use this to create a button that's going to deselect any rows that we've selected. 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 a 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 is I'm just going to demonstrate how you get access to the grid
api and column
api and 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. And push me. It goes use callback. I'm not actually doing anything with the event. The grid ref dot current. The grid ref dot current give us the current reference to the grid component, ag grid
react. And in this case, we're going to 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 going to use column
api in this particular example. We're going to use the grid
api, which is to deselect all. All right. So we've got a button here that will, so let's assume we've selected the rows and we want to provide a functionality to the user that will deselect all selected rows. Um, and there we go. So do that again. I've selected a bunch of rows. Push me. He's going to fire when the buttons clicked and using the just to repeat what I've done grid ref dot current will give you access to the ag grid
react components. And on the ag grid
react component, we've got two, um, two, uh, fields, the
api, which I've highlighted there and the column
api, um, and the column
api and the
api provide a whole bunch of functionality you can do programmatically. You can resize columns, you can, um, enable sorting, filtering, you can get more column states. Again, these, these dozens and dozens of, um, methods that you can use, uh, please look at ag grid.com for the full list. But in this simple use case, I'm just trying to demonstrate that we got access to the, uh, APIs by setting a ref. And then in this case, when the buttons clicked, we're using the grid
api, deselect all to deselect all selected rows. So just to show you again in 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. Hopefully that all makes sense so far. And the last thing I'm going to describe is events, which is what I referred to earlier, but didn't actually describe. So let's just do that now. Uh, so so you, there's so many listeners as well, um, as with APIs and column definitions, good properties, look at the grids, uh, documents, ag grid.com for all the things that you can listen on. In this case, we're going to listen to, um, a cell clicked when Excel clicked on, we're going to alert out and we're going to alert that something's happened. They use callback, um, e once I've got a log, so and whatever we're past. And to use that, we use There we go. So just to repeat some old people, we talk at the browser. Um, I've specified a listener that we get to UCM, um, using use callback. Um, when the grid, um, responds to an event and passes it up, doubles it up, up to you, it'll pass in the params. Um, 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 going to output console, the log cell clicked and what the grids passed us, which we'll look at it in a minute. And it's a hook in an event. All we had to do was specify the event we want, we want to listen to and pass in the listener. So if we go look at the browser, you can see that every time I'm clicking on a cell, a console of log messages being printed. Um, and when you, an event fired, depending on the events, um, you'll get
api, the column
api, you'll get the road
data, you'll get the cell
data. Um, you can get just about, you can get everything that you might want to use, um, in an event listener, you'll get the road
data, the column
data, the access to the grid and so on. In this case, we just printing that out. Um, 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, any, anything that you might conceivably want to listen to, you can in the grid, just check out edugo.com for what events you can listen to and callbacks you can listen to and you'd implement it like this. Hopefully it'll make sense so far. Let me just take a quick look at the discord channel. Uh, no questions there. Great. Okay. So that briefly describes, um, getting up and running very simply with, uh, the
community edition. We're going to go into more detail in the subsequent sections. Um, but this is just to remind you what we did. We pulled in the ag grid
react components. Uh, we pulled in the styles. Remember you need ag grid dot
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, um,
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. Um, yeah, we specified the field we're interested in and we pulled in some remote, um, Jason, which is an array of Jason objects, converted it to Jason and then set the road
data, um, which is then displayed in the table. We've also set some default column definitions so that all columns are sortable and filtered and have a filter on. We then showed, described how to use a grid
api, in this case, for the button to deselect any selected rows, um, which we can just exercise now with mouse. That row would be selected. And then finally I described how we can use events. In this case, we added a cell clicked events, um, and I added a listener that can listen to those events. Um, 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 a recommended way to create a theme for a good, uh, kind of theme to happen to you. So I'm not sure about, um, the CSN
css in JS theme providers. I don't see why not. Um, with how to do it, you'd have to go to the styling section of ag grid.com. Um, and it describes, um, the
css, uh, the structural
css as it's laid out and how you'd override them. Um, I'm not too familiar with outside of things, but it is, it is documented on ag grid.com on how you provide your own theme. Um, I think what a lot of people do is take one of the provided themes and then tweak it, which is, um, a lot less work than creating a theme from scratch. Um, 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, um, with SAS variables and so on. But if you really want to do something from scratch, we, we document how that's how to do that too on ag grid.com under styling, I think. Um, so we'll move on to the next section, which is a brief second. It's just how you would use, uh, ag grid
enterprise, um, and some of the features in provided there. But as I said at the beginning, this is not really about ag grid
enterprise. Um, specifically, if you want to use ag grid
enterprise, um, contact us at info at ag grid.com, um, for a free trial license, um, to try out the features. Um, 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. Um, so to check out the code for that, make sure you've selected two dash
enterprise and that's the second section that we'll cover now. So we'll stop our, um, okay, Nino, don't, don't worry about the discord, discord channel. You can just use the, uh, zoom channel as you're using now. I'll look at that. Um, it seems like other people are having discord issues. Just use the, uh, the zoom channel, uh, zoom chats. That's fine. So the first thing we're going to do, we've stopped our app that was running. Let's have a quick sip of water. First thing we need to do is install the ag grid dependency. Ag grid
enterprise. So this is going to install and save the ag grid
enterprise, uh, dependency. Um, as I said, at the beginning of the first section, at a minimum, you need ag grid
community and ag grid reacts. Ag grid
community is the core
community code. Um, ag grid
react is the, uh,
react rendering side of things. And then ag grid
enterprise pulls in the
enterprise features. You need both ag grid
community and ag grid
enterprise. Um,
enterprise, ag grid
enterprise doesn't include
community. It, it, it, it imports from ag grid
community and users that, uh, to extend its functionality. So you need all three for
enterprise, uh, code, ag grid
community, ag grid
react and ag grid
enterprise. What is the best way to confirm the grid is loaded? Um, um, best way to confirm the grid is, uh, loaded and I can inform the user to, um, upload it so I can inform the user to play around with the grid. Um, well, I think the best way to tell you, with the, our events that you can, so we've, we talked about, um, events earlier, um, and there's a, uh, first
data rendered events, um, and the grid ready events, both of those events would probably serve your purposes. So when those events are fired, you could tell the user that the grid is ready and
data is in the grid and displayed. Um, so in your use case, you'd either just see the grid, uh, but if you needed a programmatic way to let the user know, you could, these are, there's a few events that you could fire it on, uh, 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, um, inspection. Um, hopefully that answers that question. Um, okay. So we've pulled in the ag grid dependency. Let's start up our application again. So we pull in the dependency, but we're not actually using it yet. So if we reload our application, you'll see, um, what we had before. So to import the dependencies, all you have to do is import ag grid
enterprise. So by doing that alone, which, you know what, let me comment out, let me show you something. Um, so without a grid
enterprise in pulled in, you'll see the default browser context menu. And when you look at the filters, you'll see the free provided, uh, filters, um, which is a very powerful filter. Um, you can number dates and, uh, string, uh, filters. Um, 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. Um, so out of the box, if you just import ag grid
enterprise and reload your app, first thing you'll see is a console message saying that ag grid
enterprise, uh, warning message, just telling you that you don't have a license key. That's fine. Um, it won't know functionality is disabled. You can use ag grid
enterprise, um, trial it for free. If you want to get rid of this console message, you can contact us at info at ag grid.com. Um, and we'll give you a free trial license. Um, so you're free to try around and play around with ag grid
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, um, and a console message, but all functionality is enabled. So that aside, if we then go and right click, you'll see now, um, some functionalities unlocked straight away without you having to do anything other than import ag grid
enterprise. You'll see you can export that 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. Um, you can hide and show fill columns or the user rather can do this. Um, and now we have a different type of filter that we had before. We've got a set filter, which, um, is the set of all
data underneath. So now in the
enterprise, the default filter becomes the step filter. And again, I'll describe filters later on, but just to demonstrate that you've unlocked, um,
enterprise functionality, just by installing the dependency and then importing it. Um, and 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, you know, especially to Excel for a lot of users. Uh, but you can also copy
data. So user could select some rows, for example, and then copy the
data by right clicking on it or copying it with headers, um, and so on. But let's take, let's take this a little further. Say you wanted, we've got a lot of
data here. So, um, that's not especially useful even with sourcing and filtering, which is great. Um, perhaps people want to view, uh, the
data we've seen, but group it. And that's really easy to do. So we can do that by using
enterprise feature called row grouping. So let's group by country. And just by doing that, you can see that, um, the
data now is grouped by country. So we've still got the same Olympic
data we had before, but now grouped by country and say, let's say, let's say we wanted to group by, uh, year as well. It would group by row, by country and year. Oops. So, um, I'm only refreshing because the hot reloading sometimes causes issues. Um, so now you can see that we've just by adding row group true, we've grouped by country and then year. And all we have to do is specify a row group property. And now you can do this programmatically upfront. Um, say you wanted to provide a default report to users out the box, um, where you don't want to use this change
data, you could provide out 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, um, firstly showing the drop zone, the grid drop zone. I'll describe that in a second. So we'll add, um, row group panel show. Uh, wait, the group property, or group panel show. So I've added a grid property called row group panel show. This is a drag zone for, uh, various, uh, our app, um, functionality. And this, in our case, we're going to use it for row grouping. Um, but you see, by adding that property, we've got a little column here. I'm sorry, a header at the top, which says drag here to set row groups. Um, and that's great, but we also need to tell, um, 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, um, dates with milliseconds and you, it wouldn't make sense to be able to group by that potentially. So you want to be able to specify per column, what
data you want groupable. In our case, we want every column to be groupable. Um, 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. You can save that, refresh our grid. And now we can do what we did before. We can take, we can group by country just by dragging it. And what I did there, in case that was not obvious, was I dragged, selected a column, clicked on it, and then dragged it to the drag zone at the top. Um, and then to replicate what we had before, drag Europe, and then we had what we had before. We've got row
data group 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 them that, tell the grid that you always want the panel to show. So again, with very little efforts, you can unlock an awful lot of
data for the user. Um, now these, these are, I'll just very briefly finish off on the
enterprise section. There's a ton of section, some 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. Um, I'd say probably 70% of the functionality we provide, 80% of the functionality, I'm guessing, um, is free to use. Um, 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. Um, and if you see a little E next to it, then you'll need an
enterprise license. Um, but again, you're free to use aggrid
enterprise and try it out. Um, and if you want a free trial license, contact us at info at aggrid.com. Um, and then you can also take it further and actually buy a license if that's something you decide to do. Um, so I think I'll leave that at aggrid
enterprise. Um, I assume no one's got any specific questions. I'll just recap what we did. Um, so firstly, we installed the aggrid
enterprise dependency, uh, with
npm and saved this into package.json. Um, you can see as the three dependencies we have, we have aggrid
community, which is the free, uh, dependency, uh, free
community edition, which has, uh, the, uh, about 78% of the code functionality that you need. Um, aggrid
community is free to use. You don't need a license for that. Aggrid
react is the reactor rendering, uh, side of things. So you, at the minimum, you need aggrid
react and aggrid
community. And if you want to use
enterprise features, you pull in aggrid
enterprise and you need that as well as the other two to unlock, uh, the
enterprise features. And that builds on top of aggrid
community. Um, and lastly, you need to keep ensure that your major and minor versions are in sync. You, you want to always have major and minor versions in sync. So you don't ever want to have 27.4 and three, for example, a mismatch or 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 dependencies you use. Yes, aggrid supports
typescript. Um, we ship all the typings that you want to use. Um, we document how you can use it with, um, TSX, for example. Um, so for example, um, if you wanted to use a grid ref, you could specify it as aggrid
react, something like that. Um, 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. Um, and if you did something like this, you'd have, um, auto-complete. So, yep, it's pretty supported. Aggrid
react actually, um, aggrid is actually written with
typescript. Um, you don't have to use
typescript, but it is supported. Um, okay. That's, that's finishes off, uh,
enterprise features. Um, 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, uh, ping me on the, on the channel and I can repeat it. Um, so we'll go on to the third section, which is renderers. Um, and this is, um, using custom renderers. So out of the box, the grid will show you, um, row
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 the string, it'll show a string. If it's a number, it'll show it as a number, it'll show a rule number. If it's a complex object, you'll probably just get object objects, but you can, um, with value getters and so on, pull out, um, pass complex
data and print it out. But ultimately what a user will see will be a string representation, um, or sorry, something like that, simple
data. But what you can do is provide, um, a
react component. So perhaps you wanted a spinning wheel or, or a slider or anything, um, anything in this, in these rows and columns, um, including headers and filters can be, uh,
react components. So in this first section, we'll just document and describe how you'd use a cell renderer, which is probably the most common thing, um, that you'd probably want to create a custom renderer for. Um, and anything that you can do in a
react component, you can pop into the grid. So if you can have a
react functional command or cost based components and it renders
html, um, ultimately you can use it in the grid. Um, so the first thing we're going to do is we're going to have a simple, not very useful, but a simple renderer, my renderer. And this is just going to show, uh, uh, sorry. We've got a simple, uh, renderer here and we're going to use this renderer on the athlete column. So this is not a terribly useful renderer, obviously. Um, but again, we've got a simple functional components and we've passed it. We tell the grid to use this component, my renderer, and we want to use it in the cell in place of a cell renderer. So instead of representing or outputting the raw JSON
data, we're going to output whatever the, uh, renderer does. And in our case, regardless of the underlying
data, we're going to show hello world. Um, and 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 provide us. When we render each column, um, we can, give me a second. Whenever each row and cell is, uh, rendered, if you've got a custom renderer, we'll tell the grid, we'll call your renderer and instantiated 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 the, let's take a look at the props that they use, uh, the grid parser. So you'll see a whole bunch of outputs here and let's each one for each row, um, will output, um, the P the props pass 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 you are provided to you, but some of the key ones are the column, deaf, the column information, you can see the
api, um, 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, they've got value, uh, merits, the organ. Um, 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 render a little bit more useful and let's use the
data we're given. So P dot value. Um, and with that, we should end up with a P dot value. P dot value. Um, and with that, we should end up with what we had before. So we're using, we, we visually, from the user's perspective, we're seeing what we saw before the rows and column
data, and we're seeing, um, 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 fill and outputting it. So we left with what we had originally. Um, but let's say, let's say we want to do something a little bit more realistic. Let's say that in a renderer, we wanted to, um, 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, let's do something like that. Um, 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, um, the point. P dot value. And I want this to be a string, uh, template string. So. And here we go. So we save that and I'll describe what we've done. If we look on the browser, we can see a button that says click me. It actually should say dollar. That's why the business called dollar. So we've taken our simple renderer and extended it very slightly. We've now got a, um, an event listener that's going to be fired when, um, the dollar symbols clicked, um, and, um, it'll output dollar clicks and the value of that cell. Um, so again, this is a very simple renderer, right? This is not something you would probably do. Do something much more, uh, complicated. Um, but, um, let's take a look at that. So we click on that. Got dollar clicked and then the value of the cell, Natalie, which is the value of the cell we clicked in. So again, this is really simple. Obviously, um, you would probably do something more complicated, um, with your
data. Um, it's just to demonstrate that any
react component that you have could be rendered within the grid. Um, 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 custom filter, um, you'll get the state of the grid and the value of the cell you clicked on or so on, but you can compliment, um, you can add to via props
data that you want. So let's take this further. Let's say that, um, let's say we want to pass down the button text. So, so you want a generic, uh, uh, components and you want it only to differ by, um, what you pass in. So you can compliment it with an object and whatever you specify in here, uh, we'll make available in the props of the components as it's dynamically and crazy. And whatever you put in, in the dynamic, uh, the params can be, um, anything. Excuse me. One second. Sorry about that. Um, so we don't do anything with this
data. We'll simply make this available. Now case we're going to do button text. Um, I'm going to say the button text is going to be at the bottom. Um, and that will now be available to us. Um, so we're going to do um, 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, um, button, what did I call it? Um, I made, I think I made a typo cell renderer renderer. It helps if you spell probably. So I made the type of before and then spelled cell renderer params correctly. So if we look at this, we've said on the athlete, uh, column, we want to provide a prop called button text with a value of athlete button. And if we look at 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, uh, P dot button text. And you can see that in the red browser, we've got athlete button. So for example, you might want to use this renderer and make it a generic renderer. Um, and to be different across columns only by props that you pass in. So let's just demonstrate that you could use the same renderer, make a generic, and we'll, they will describe this a little further later with Phil and fields. And this could be age button. So you can see that we've used the same components, this render here, and we've made a generic, um, and we've differed only by the pops we passed in, um, button text in this case, but it could be anything. Um, that's just to demonstrate how you can compliment the renderers you use and provide some extra metadata or props to them. Um, lastly, let me show you how you can use a simple renderer. And this is an inline renderer. And this is probably something you might want to do if you're doing
testing or that was a super simple renderer, um, something you're not going to share. You can just use an inline renderer. Um, so you don't need to specify it externally. You can say something like, um, uh, my inline renderer P dot value. So this is the same as above really. Um, 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, um, you can inline it as I've done there. Okay. So what's next? So let's say that you've got a, uh, scenario where you want to have different renders based on, um, the value of the, the column. So you might want to say, uh, renderer X if the
data is one and renderer Y if the
data is two, you can dynamically choose what you're going to show, um, based on cell renderer selectors. So let me show you that. So you can have it static and that's probably the, your, 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 going to do it based on, uh, row
data. So if, uh, Peter, if the value is equal to 2000, we're going to return and specify components myself, my renderer. We're going to use this on a different field. Actually, if P dot value equals 2004, we're going to return, I'll describe what I've done here in a second. In this case, we're going to have a inline components. I'm just going to 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. So I've moved this. I've created, I've added a property called cell render selector. Um, and that's fired per, uh, row
data for this column for every row in country column year column. This will be fired. Um, and it'll pass down P, which has the
api, grid
api, column
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 refer it, return myself in my renderer, the one we specified above with the button. Um, and if the value is 2004, we're going to create to return a simple inline components. And the value is neither 2000 or 2004. We'll just output the raw value. So let's say 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 going to return this inline component here, my inline components and the value. And finally, if the value is 2000, we're going to use my renderer, um, with the button, um, as we said before. So if you want some rows to have a special functionality or a renderer, 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, um, um, am I muted? Gosh, I'll take a look. I don't think I'm muted. Can anyone else hear? Not to me. He's not. Oh, great. That's good. Um, so I'm, I'm sorry for, uh, for Joe. Um, it must be something on your end, I'm afraid. Um, so just to repeat, um, whatever we return here, if it's, if it's a custom renderer, we can compliment it with cell render params and whatever we do in cell render params will be made available in props. If you don't specify a component and a renderer to use the griddle, simply output the raw value of the, um, of the, uh, the Jason
data. I hope that makes sense. So, uh, yeah, sorry, Joe. Um, I'm not sure I can help you. If other people can hear, um, it must be something on your end, your end, I'm afraid. Um, but I don't think I can, I don't think I can help you Joe. Apologies. Well, you can't hear me, I suppose. Um, um, so we, just to recap, we described how you can specify a cell renderer. Um, all you need to do is sell a renderer and then your renderer. So in this case, my renderer like that, you can also have inline renderers. Hello. Like that. Um, and finally you can have dynamic cell renderers. Um, and you can choose different renderers based on the column
data, but hopefully that makes sense to everyone. Um, that was pretty quick. Um, I'll just like another sip of water just to recap. We remind you that the renderers I've done here are pretty simple. Um, uh, they've simple, I've got simple buttons and simple
data, but you could have anything. You could have a graph or, you know, a dynamic slider or spinning wheels, anything that
react can render in a component's functional or class-based components, you can render within the grid. Um, the size of the component would obviously change the size of the row. So if you had this component with athlete button, if you had this 30 pixels high, then the whole row would be 36 pixels high to show that. But this point is anything that you, any, any
react components you want to render in the grid, if it's a valid
react components, it can render in the grid. Um, um, how does the cell render if the lines too long? Okay. So I've just, I've kind of answered that. If you had a component, say that was outputting, um, a multi-line, um, components, um, 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 hundred pixels high with a paragraph next to it, then the entire row, so this column would be that high, a hundred pixels high with text next to it. And so the whole row would be a hundred pixels wide. The row height is determined by the highest, um, highest, the biggest cell in that row. So if all the other rows, um, cells are 20 pixels high and the dynamic renderer has to a hundred pixels or high, it'll be a hundred pixels high. 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. I have another some water here. Okay. So we'll move on to the next section. Um, and it's going further with, um, custom renders, uh, sorry, no, not to talk about filters. So we're going to touch on this section on filters in the first section or two. Um, I showed you how to enable, uh, filters, um, and out of the box, um, with
enterprise edition, you get said filter as a default, um, 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 let's just discuss for initially for now. Um, we provide out the box three, um, filters out the box in the
community edition. Again, the
community edition is free for you to use. Um, and commercially, you don't need a license and out 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 going to remove the renderer code just for simplicity. Remember the code is on. If you want to recap what I've done, um, just go look at the GitHub repo for the particular section you're interested in. Um, and it'll be there. I'm just going to 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, uh, we're back to a simple
community edition. There's no
enterprise code here now. So the first thing we're going to look at is the, uh, text filter. And that's, um, if we just do filter true, depending on, um, uh, I'm going to second, so it's an offline link. I hope I'm saying your name correctly. Um, so that's the repo. And then just to recap, in case you missed for the section, if you go to the branches, um, 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, uh, Oskander. I'm probably massacring your name. I apologize. Um, but each of the branches is a section. So we're on section four, um, and it'll show the code. If 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 equals 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 use an
enterprise edition, it'll use the set filter. Um, so most of the time the filter true is good enough for most people. You'd probably want to use the default, um, the, uh, vision renderers are no, no renderers are not
enterprise edition. In fact, most of what I'm describing here is
community custom components, renders, editors, filters, which we'll get onto in the next section. All of those are free to use. Um, um, I, I will highlight and I'll specify if something I'm doing is
enterprise. Um, but like I said, right at the beginning, most of the talk, most of this workshop is
community edition. Um, I'll highlight if something I'm doing is
enterprise. So custom components of any type are
community edition. So whatever, if you're doing a custom, uh,
react components and you want to use it in the grid, that's, that's free. You don't have to use an
enterprise license for that. So the road grouping I showed you by all by grouping by year and by country, that was a, an
enterprise feature, for example, but everything else you see in this grid. So now is free, including the renderer you saw before. Um, that's all free to use. So, um, yes, rows are virtualized out of the box. You can override that. Um, but yes, the rows are virtualized and columns actually, um, you can override that. So see ag grid.com for details on how to override that, but by default, yes, they are. Um, and so that was, so filter tree will be the default filter. It's the same thing as if we did ag text column filter, and I'll, I'll go through all the three, three ones provided. So if we do that and we look at the filter, you'll see nothing's changed. Um, we can still use Mick or Michael or Jung or Jung. Um, and although this is a free out of the predation and all three, uh, filters being described are free, they super powerful. So don't think that just because it's free and provided without it, without the need to get
enterprise code, they're not powerful. These are super powerful and can probably take you a huge amount of way, um, uh, on your way to an application. Um, before you need to consider a custom, um, filter or an
enterprise filter, the, um, the, the provided filters are very powerful. So check out ag grid.com for what they can, what they can do. I'll describe briefly here. Um, 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. Um, we can say that doesn't do anything because it's not equals not contains. Well, and now Michael helps a day. So, and then you can provide all functionality. So let's say we want to do contains Michael. That gives me everything with Michael in, but we only want it. And if it contains maze and then you could do all so Michael or maze. Um, 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. Um, this is none of this is
enterprise specific yet. Um, if you see an error in the console here, by the way, that's not to do with the grid. That's just, um, 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, um, not, not a text one. And it's equally powerful as the, uh, as a 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 an equals. Um, so you could say it's less than 30 and it's greater than 20. Um, and it dynamically everything, all the ages of these winners between 20 and 30 are equals. I mean, greater than, so all ages between a greater than 20 and less than 30 are displayed. Um, and that's the number filter. So it's similar to the text filter, but it does number appropriate, uh, filtering. Um, 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 tell 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 24 08 2008, 24 08 2008, but not 20,000. And that doesn't actually work. You'll notice that the dates 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 there, it's just the string. So it looks like a date, but it's actually just a string. So when the date has been applied and trying to use, uh, none of these will match because they just strings. We'll show, I'll show you how to fix that, um, later on. Um, now we're going to use two, uh, show, finally to show you two more, uh,
enterprise filters. So we're going to enable. These are
enterprise filters. Um, so you would need an
enterprise license for this, but this just rounds off the one, 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, um,
enterprise. And I won't spend too long in this. I'm just wanting to describe what they do. Uh, so, you know, call them filter. And the last one is filter. So we're getting 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. Um, the set filter, it provides a set like you'd see in Excel, uh, same sort of thing. Um, and provides 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, um, 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 then press enter, which I think is pretty cool and filter. So for example, I'll just show you what I did again. 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 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, um, as a, as a starting point. And then the last one, which is arguably the most powerful filter is the multi-filter. Um, and this enables, this mixes two types of filters. It provides, um, 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 edggrid.com the
documentation for what you can do. This is, it can do a lot more than I'm demonstrating here, but here you can see our text filter and a set filter combined. So you could say, um, and this is not terribly useful with the date, um, for the number. Yeah, let's say it has six. That's not a great example. Um, I'm going to move this set filter to another field, actually. I'm going to use it on sports. I think that's more, more useful. Um, here we go. So, so we wanted to contain, um, 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. Um, so it filters the selection below. So whatever you do at the top narrows down the selection on the bottom part. So if we did a only sports with the letter a nuts can reduce or shown. And then before we could have something like 10 and it would reduce it further and would apply the filter with an enter. So I know it's pretty brief on those to the set 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. Um, but with a little bit of configuration, the
enterprise filters, I've described the symbols and the multiple as well as the three, three ones, the text number and date ones can do a huge amount of functionality out the box. I won't go through it here. Um, just wanted to show you what they were and how you could use them. Uh, but check out a good.com for
documentation, how you can really make use of these powerful filters, um, out the box. So I'm going to remove the
enterprise filters again. Um, we're back to, uh, fully
enterprise, sorry, fully
community, um, application, we're not using
enterprise in the
enterprise functionality here. Say you wanted to override the bounce. You wanted to, uh, slow down. You wanted users to, uh, uh, have time to think before they, before a filter was applied, you could add a debounce. So you can just compliment the product, the filter in the first place. So to filter it, like we saw before with the renders, you can have cell render of params you can have, you can extend or compliment, um, a filter with filter params. And as you'd imagine, if you've got a custom editor, which we're not going to 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 want to change the debounce. To be zero. So for this filter, which is age, we want the, uh, to apply straight away. So there's no change. Whatever I type, it gets acted on straight away. Um, if you want to just slow it down, let's change it two seconds. So now if I, whenever I type in here, it's going to not respond for two seconds. I type 23, one, two, bonk. So whatever I typed in there now, there, it waited for the debounce of 2000 milliseconds, which is two seconds before applying. There's a whole bunch of things you can use to extend the filters and I'll describe buttons in a second. But again, check out aggrid.com for all the cool things you can do with a grid and the filters specifically. So does aggrid support tree shaking and
enterprise is around? Yes. So yes, it does. So I won't go into this too much, but what we're using here for aggrid
community, aggrid
react and aggrid
enterprise, uh, uh, 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 aggrid.com, go take a look at building and
tooling and look at packages versus
modules. So what we're using here with aggrid
enterprise and the
community are the packages. Um, and your 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're only pulling the, uh, 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 pull in those two
modules. Um, 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. Yes. So tree shaking is supported, but if you want to maximize, uh, the size or reduce the size of your bundle, go take a look at the aggrid
documentation or packages versus
modules, what the differences are and how you can use those. Can you retrieve the states of filters from aggrid? Yes. And I will describe that in this section a little later on. So just wait for that. What about is the date use case where you can't load all the
data in one go? I'd enlarge and nest the
data. Absolutely. So what we're looking at is that's something called, um, uh, client side
data, the
data we're using now, the, uh, 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. Um, also all the
data is in memory and only some of the
data is rendered because of virtualization, but still, if you had a million rows, you probably don't want to pull a million rows into your browser, you know, it'll probably kill your browser. Um, 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, um, you can get various options. So for the free version, you can look at, um, uh, uh, infinite roles, row scrolling, take a look at the docs for that. Um, I can't remember where that is on here. Inverted row model. So that's the free version. And this is something I'll, I won't go into it, but the infinite row model is something that you could use in the
community edition for, as the
data implies, infinite row
data gets chunks of
data as you go. Um, and then there's also
enterprise, um, 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 could look at the infinite row model. And if you're using the
enterprise feed version, you have even more, uh, ability. So you don't have to put in all your
data at once and you can use pagination. This is another option. So take a look at that in aggrid.com row models and pagination are the way to go. Um, 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 path. And when that's called per row per cell, um, 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 cell has been rendered per as the renderer has been chosen. Then once you've got a chosen renderer, you get the same
data in your renderer and you could 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 rendered to show and in within the renderer, you can show what to show depending on the
data. So before the
data is actually displayed, you've got a whole bunch of points in the life cycle to choose what's shown and how it's shown. Um, 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. Um, so I've added 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, uh, field. So let's say it 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 will reduce the amounts of boilerplate code you have to, you have to do or want to do. Um, so let's remove that. We don't want the debounce of 2000 milliseconds in our case. Um, so the last thing I want to look at with filters here, except before we get to filter state, um, which is a previous question, are buttons because I think they're quite useful. So let's go look at this again. Um, we've got filter frames back to age. Um, 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. Um, where did I specify that on the age? So now you can see two buttons have appeared and I'll describe the other two. These two are these four buttons in total that we provide at the box. Um, now the filter won't apply, um, until a user clicks on something. Um, so I can type 25 and debounce is ignored yet, even if you specified it and nothing will happen until I click on apply. Um, and I can clear any current filters, um, and then reapply it. So just to repeat that. So if I want to have 25, nothing happens until I click apply. This is sometimes the desirable, some, some users type in a whole bunch of things you don't want, uh, the regress to filter and unfilter as the user's typing. Maybe you want to use it to type some complex, some complex formula or regex or something like that. And only for to apply when you click apply. Um, when I click clear, it'll click, 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 panel symbol, a little filter symbol. So the filter is still in place. Although we've cleared the UI with care, the kid, you, I won't apply until we click apply. So apply applies the, whatever you've specified in the filter clear will clear it, but not apply it for you filter it again. So I hope that makes sense. Um, let's look at the other two buttons. We've got, we've got, uh, cancel and we've got, uh, reset. So again, just to remind you that this message you see here about costless, that's not an age grid issue. It's a hot reloading issue. Um, 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 one. 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, for example, if I had, uh, if I had some really long filter, let's say I did apply, so, and I made a mistake and I was doing something else and I thought, oh gosh, I don't know what I had before. Um, 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 equal to 25. And if I typed that and I don't want to change the filter, I just want to 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 ones. 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 now 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 will clear the current filter. That's a lot to take in with me just talking. Um, but if you're not sure, if you want to remind her, go to aggood.com and it describes the buttons more clearly than I probably have on 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 want to see what the buttons do, check out aggood.com. The point we have to demonstrate that we provide four buttons out the box and 99% of times those four actions are the ones you'll want to use in your application. Okay. So let's remove these buttons and now let's go back to take a look at why. Remember the date filter is not working because the date filter applies the filter, expect date object in the row
data. Um, and we don't have dates in the row
data. We've actually got just raw strings. So what we're going to do is provide a comparator and I'm going to copy this code so we don't have to type it, but too much to type. Uh, where is it? Oh, there we go. So I'm copying this just because it's a favorite 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. Okay. 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 that the underlined
data is just a raw string. So what we've done here is to, um, provide a filter parameter and a comparator and this is useful if your underlined
data is a complex object. Um, perhaps it's some weird
data that you need to pass before you can do something with it in
javascript. Um, a comparator allows you to do it. It gives you the value from the filter, which in this case is 24 dash zero eight dash 2008 and the actual underlined cell value, whatever it is in our case, it's a string. And so in this case, we're going to take the string and pass it to a date object. And then we're going to compare the date value. I'm not going to spend too much time on this actual comparator. The point is that we can, you can override what is compared by providing a comparator via 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. Um, that closes the loop, I think on all the filters. Uh, thanks. Would virtualization sorting filter still work on the server side model? Yes, but it pushes the responsibility onto you, the developer. So for example, if you're using, uh, um, a server side row model with, say your
backend, your
database has got a million rows in it and you're only showing, only pulling a thousand rows in the grid, obviously can't sort or filter road
data. We don't know about. So what would happen there 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, um, and then updates 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, um, S to X. Um, we would tell you that now that's, that's what the user wants to do. You would get rows from S to X and, and return it back to the grid. So it pushes the responsibility from us at the moment on client side
data. We can do all sorting, filtering, uh, 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 repose, GitHub repose that show you how to do these. Um, there, uh, we're going to cover inline entity with a
community edition. Yes. So I can do that briefly. Um, you can have fairly complex editors, which we're not going to cover on this, but to make a field editable, um, by default with just simple inline entity or you can, all you have to do is say editable crew. So by default, that's all you have to do. Uh, what I 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. 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 a callback as well. You can have it per row and per cell. You might want some cells in some rows to be editable and not, um, as before we'll pass down to you as a parameter, the state of the grid, the state of the cell, um, APIs and all that sort of thing. And you can dynamically determine what's editable. And then finally you can have, um, cell editor, and that can be a
react components, um, your
react component, which we're not going to describe today, but, um, it could, as we show it to all with the red, um, editor, I'm sorry, the renderer earlier, um, 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 the simplest use case is to just say, um, editable and then the cell will be editor. I assume that's what you mean by inline editing. Um, okay. So the next section we can look at is, uh, filter states, which was a question we had before. So whenever you do a, um, a filter operation or sorting, um, or in just about anything, you can get the states of the, um, uh, the, the state of the filter or the state of the filter. And you might want to say a user's, uh, filtered on three columns in a specific way. And they want to say that every time that they opened up the application, it restores. You might want to 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, what we can do with it. So to save the states in our case, we're not going to say it to a
backend. We're going to just use a ref for this. Um, and we're going to 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're going to say a use ref that we can use to store
data. Um, and we're going to have buttons that save and apply it. And these are going to, we're going to have, we're going to add the buttons in the section in a minute. So in what's in fact, instead of me, I'll type, I'll type it on button, save, let's see how many mistakes I make while I'm live coding here. I'll describe as I go line by line, what I've done. So we're going to use this callback in a second. Um, but what we're doing here is we're using a grid ref, which we used earlier, if you remember on the grid components, grid ref.currents.
api gives us the grid
api instead of a, as opposed to the column
api. And we're calling get filter model. And that'll give us this JSON representation of all current, um, um, models applied. So let's, let's start off with that. Let's just take a look at that filter model, the unclick on button, save, um, save. 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 how exciting, um, it's an empty object. So let's, let's do something more interesting. Let's say age is equal to 25. And now if we out save it again, we now see a JSON object. That's good age. The filter type is a number. The type is equal to filter is 25. Now you don't need to understand the outputs of get filter model or set filter model. Um, you don't have to, the grid will provide what the current state is. You can save it and restore it. Um, 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 JSON object is two age, but age and year. So we don't actually save in the filter as it's specified. We're just outputting it. So you can see that what the filter model is doing. So let's save that with, uh, say filter dot current equals filter model. So on the, the ref with pride above on current, we're going to save the current filter model. So let's have on button apply. And with this apply, we're going to, um, apply whatever is saved and I'll demonstrate how that works in practice. So we can have, uh, a constant filter model equals saved. Again, I'll describe what I'm doing after I don't. Um, red ref dot current dot
api. So we're going to call another
api method on the, on the grid and I'm going to go set filter model, filter model, and then we're going to add a button to actually use this button. So what we have here now is, uh, push me, which I will comment out just for simplicity. So we don't see that. So we've got to save filter states, which every time I click it, we'll save onto our grid ref. Um, the, uh, the ref, uh, the state of the grid and apply will pull off the current state of the grid, um, filter and apply it. So let's try that out. Let's, let's apply, uh, Mitch on there and then country, um, contains Australia. So we've got, uh, the current state is that I meant to click on the filter. Sorry. Uh, on the method, we've got anything that contains Mitch and in the country, anything that contains Oz. So we've got Australia and Austria and anything in the athlete name of Mitch. So if we save that, um, let's say we go change the filter. Now we go, we don't want Mitch, we want, uh, Tim and we want, uh, countries that have no country filter. Let's say we've got no country culture. So we've changed the filter. We've saved it earlier. We had, we had an athlete filter and a 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 go back to where I was before we can apply the filter states. Um, and now the, the state of the filters are back to where they were before. We've got the athletes filter with contained Mitch and the country filter, which contains Oz. Um, 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 Jason
data. And you can, um, uh, you can convert that into a string and maybe save it to a
database and then convert it back to Jason and restore it. But what we've done is get the current state of the model and save it onto our ref in our use case. More realistically, you'd save it to a
backend of our
database. Um, 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. Um, that's at a high level is, um, how you would get the states of the filters across the grid and how you'd reset them. You can manipulate that Jason
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. Um, before I move on, let me, I hope that answers your, whoever had a question about filter states, I hope that answers your question. It's actually pretty easy. I mean, to
api that get filter model, get this, um, current state of the filters and get sort of set filter model or set it depending on what you want. Let's look at the questions here. Okay. And then, so we need to, uh, say callback well for, I think if you're asking about editing, um, I'm, I'm not sure what you're referring to there. I'm afraid, uh, Charles, when you say, so need to add, say callback, uh, maybe you can ask again and expand a little bit about what you're asking there. Um, I suppose it's the same. If you have a few edits and cells and to want to, uh, save all the changes in one action. Yes. So, um, by default, the grid, when you, when the user enters an editor cell with editable to be true and clicks enter, the underlying Jason
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, um, you might, you might not want to underline change the underlying
data, but rather send it up to the Redux store. You can, um, listen to the save events, um, and not save it down, you know, tell the grid, don't save the
data in the editor and instead send a fire or four events or ducks, and then it would fold it back down to the grid. Um, so yes, you could, and, uh, depending on your use case, you probably would. Um, I assume I can use this to store multiple states in history for undoing. Absolutely. So the grid actually has undo and redo functionality. Um, check out the grid, uh, the
documentation for how to do that. Uh, but if you wanted to do your own, perhaps it was very complicated, um, undo and redo. Yes, absolutely. Um, for each edit operation or each filter operation, you could save the states again, 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. So we've just shown filter state here, but you can get, um, sorting states and all sorts of states. The most common are edits, um, filter states, uh, grid states and, uh,
data states, um, and, uh, filter states, but using events, you could capture anything and, and apply that as your state. Um, okay. I hope that makes sense. So let's move on. Um, so next we'll look at, uh, applying, well, actually one other thing I can do here. So we can add, say you wanted to clear the states, you could on button clear. I'm going to save this. We don't need the filter model in this case. I'll tell, I'll write it and I'll describe what I've done. So, I mean, it doesn't really matter in this case, but okay. 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 not athlete, that's Mitch. So what am I filtering on there? What is that? Sorry, made a mistake. Contains Mitch. So the user has done some filtering and UN he's done some filtering or she's done some filtering. Um, and then you, you want to provide a functionality where you just reset all filter states or sortable state or so on. You can clear it and this applies to all the states, filter state and sort and sorting states. You can apply an empty model, which is just an empty object and that would remove any, uh, sorting or filtering that had been applied. Just a useful little, uh, trick that's occasionally useful. So the next thing I want to move on to is, um, floating filters, which are pretty useful. So if you want to have a floating filter, all you need to do is filter. And that'll enable this. So this will enable a floating filter will enable, uh, 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, then I remember default column diff is, uh, applies to all columns. You'll see that all of them have filters. Um, 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, because it was pretty quick. We had default filter true in the default column depth, which means that every column had a filter. But to demonstrate what I'm talking about here, um, I removed that and only the columns that have a filter field, the dates, age and athletes have filters. Um, so that means that only athletes age and dates have flow can have floating filters. So although floating filter is enabled in every column, it'll only appear for columns that a filter is appears or is present. Um, and you can do the same thing in line that you could do with the actual filter. 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. Um, and all we had to do there was, um, add floating filter be true. So you get, it's pretty, I think this is a pretty useful piece of functionality. Um, and all, and most of the times all you'll have to do is place five floating filter equal to true and out the box, you'll get some pretty cool functionality for the user. So the user doesn't have to click on there, um, and do stuff you could simply, or she could simply do it in line. Um, what else did I want to talk about? Okay. So the last thing I wanted to talk about on filters, um, is clipping. So occasionally, depending on your applications and depending on where you're seeing it, um, you'll 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, uh, 300 pixels and that looks fine. But if we look at, if we use something like a set filter, and I'm only showing you're showing the set filter for demonstration purposes. Um, 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. Um, uh, hang on, what have I done? 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. Um, um, so I need that to be even smaller. Let's do 150. There we go. So as you can see, this, the main, the filter menu has been clipped, uh, because the grid only has 150 click, uh, pixels to play with. Um, it's been clipped at the heights of the containing pair of Dove. Um, 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 pop-up parents or what we call the pop-up parents will be the parent Dove. But in a use case like this, where your grid is pretty narrow and pretty small, and you still want to show the full context menu or grid menu, um, in filter menu, you can specify a pop-up parents. And this is useful specifically for, um, uh, filters, but it's useful in other places as well, that context menu. So I've said document body to be the pop-up parents. And you'll see now that the pop-up is showing fully and breaking out of the parent Dove. So it's a small little thing. I just wanted to highlight because it's going to be a phase in the, via gotcha. Um, and all you need to do is specify the pop-up parent by default. You probably want to use document parents, but you may want to use, um, some other elements. Um, I hope that makes sense. So if you see clipping on your menus, take a look at pop-up parents. Um, and you probably want to set it to be document body by default. If you've got very narrow, um, or very, um, certain grids, could you specifically take a look at the questions? Patricia has asked, could you have a top high level search outside the grid table? Yes. These are a thing called a quick search, um, quick filter. Um, and a quick filter allows you externalize filtering. So hopefully you can see my browser. Yeah. I've got a little text box 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. Uh, can you place the floating filters above the table headers? No, you cannot by default. Um, but you could create, so if you, if you needed to perhaps your UI designs and specify that, you know, first of all, there has to be on the top and it is at the bottom. You could create a custom header, probably be a fair bit of work, but you could create a custom
react components that does that for you. But at the box, no floating filters are as far as I, as far as I remember, uh, below the actual, um, uh, uh, headers with this filter or publicly full screen on a mobile device. How does the grid look on mobile? So the, yes, yes, they would work on mobile device, but you need to be careful with, um, having tabular
data on a browser and on a mobile device. And this is not just a good, this is any tabular
data. Um, you probably don't want to show this sort of thing on a, let me show you back to, uh, three, 500 on a mobile device. You probably don't want to show many columns like we've got you and many thousands of roses. We've got you on a mobile device. You'd probably want to show a truncated view and fewer columns. Um, 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, how to think about, um, 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 it's probably okay on a tablet on an actual mobile device. Um, yes, you can show it. And yes, the menu will be, if you filter, it'll be shown. Um, it probably wouldn't be a great UI experience. So smaller grids, um, and consider a different
design decision on small devices. Tablets, tablets are okay, but on mobile phones, less rows and columns is probably what you want to do because it's, it's a pain to have to show through many, many rows on a mobile device. But yes, this is the answer. It will work. It works just fine on a mobile, uh, scram mobile device. Um, it's more of a
design question at that point. Okay. Um, what are we going to look at next? Okay. So the last thing we're going to look at today, um, coming up to two hours, it's about, uh, this workshop was planned originally at about two hours. So we're going to overrun a little bit. Um, if you have to go, that's fine. Um, you can take a look at the GitHub, um, repo and I think this has been recorded so you can, you can look at the, uh, the recording afterwards if you want to track, but the last thing we're going to look up and look at, um, is custom filters. So we've looked at what
azure grid provides as well, but we're going to look at custom filters. So we've looked at what age group provides out the box, three, uh, three ones in
community, and then two additional ones, uh, in the
enterprise. So a total of five, if you use an
enterprise, but if those don't work for you, um, and again, I look at ag grid.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 renders, you can have a custom filter. So the first thing we're going to do is we're going to create a new file and we're going to call it year filter. Yes, Mohammed, I'll share, I'll share the link in a minute. That's fine. Uh, filter.js. Let me just share that link quickly. There you go. Um, 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. Um, if you click on that, I'm going to number five custom filters at the moment. So I'm not going to attempt to write out this. I'm going to, uh, copy it and then I'll go through it and describe what we're doing. So like we did before with the, um, like we did before, we can have a custom
react components, uh, like we did with the renderers, but this time we're going to have a little bit more of a complicated, uh, components and this time we're going to do it for filters. So there's two ways to have components at the moment and
react. You can have functional components like, like a hook, which we're going to demonstrate here or cost based components. If you're using a functional components, um, there are some life cycles, life cycle methods that the grid needs to be able to call, um, to, uh, for grids, uh, for filters to work and editors as it happens and other things. And to expose those to a, um, an external user, you need to use a forward ref and a use imperative handle. I'm not going to go into too, too much about how these work. Again, this is, that's a
react specific topic. So go take a look at the
react documentation. Um, if you want to know, but in a nutshell, these methods here that I've highlighted is filter active, does filter pass, get model and so on. Um, those are, um, grid filter specific life cycle methods that the grid needs to be able to call on the components. And for the grid to be able to see those, um, or for any components to be able to see those methods, you need to expose them via use imperative handle. If you're using a cost based components, you don't need to use forward ref and use imperative handle. The methods will just be exposed by default. I hope that makes sense. Uh, 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, uh, methods is filter active, does filter pass, get model and set model for this first pass. We're going to ignore get model and set filter and set model. So we're going to return undefined model and do nothing with set model. So we can ignore those for now. We still need to provide them because the grid will call them when things happen. Uh, 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, so 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 filter state is not equal to off. So if by default, the filter state, um, value is off and if it's off, the filter is off. If the filter is not, is any value other than filter state. So in other words, if it's a year, um, it will check, it'll call does filter pass per row. So per row in our particular case, we've hard coded it and we're going to check out the, uh, year value. And if it's 2008, um, it's going to work. So in our filter, we've created, uh, two inputs, um, it's a radio button and the filter is either going to be on or it's going to be off. And if the user clicks off, the filter state will be off. If the filter, if the user clicks on, the filter state will be on. Um, remember we've got a simple filter where the value is simply hard coded and it's hard coded because I just want to talk about the params or props that's, um, happens here. And we have two listeners, two listeners for those buttons. One will set filter states and one will set on and one will set filter states off. So we've got a full term, but we're not doing anything with it. Let's go import it. I'll remove
enterprise. We don't need that for now. Um, and I'll remove the other filters for simplicity. So import, we've imported the filter and we're going to apply it to you. So I 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 components, it'll use that
react component. So let's save that and go take a look at our app. You can refresh that to just 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. Um, and then, so by default, the filter isn't active. You can tell the filter is active because there's no little filter symbol here. We click on on. You'll see that the row is 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 off. And the filter applied. We missed one step. Apologies. The filter only applied because of this lineup highlighted in the browser and in the IDE. So on the props part to the filter, there's a method called filter changed callback. 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 filters changed, please act on that. So every time we change the filter state, we call filter changed callback on the props and the grid will call is the filter active and if it's active, does filter pass per row. Okay. It's also prepared the link. Thank you. Hopefully that will 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 use profile filter to be useful is filter active and does filter pass. Get model and set model 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 began to do later. So that's our bare minimum filter. Now, I've hard coded this because I want 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. If the filter wasn't active, the does filter pass 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 does filter pass 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 saying filtering by 2008 based on a radio button. So let's see if we can make this a bit more useful. 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. 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 going to 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 will be filter text. And we're going to use it. 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 within the grid year filter. We've externalized 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. So we can say const field. So one of the values passed to the props is the call def 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 call def, the field, the filter, filter params. But the one that we're particularly interested in is this field year and that's made available to us in the via the props and we can extract that. So we can say that we want to filter field to be 2008. So this is going to have the same effect as what we had before. We're going to say wherever 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 equals 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 going to 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 going to go. Now 2000 criteria is 2008. And now 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 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 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 a radio button. 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 the placeholder 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... So I'll just make sure this works and then I'll describe what I've done to close the loop. So now we've got off, we can put on year instead of this year. So oops, that means 2004, 2006, 2008. So we've got the off state. We can apply filters on radio buttons now. So we've made it a little bit more generic based on radio buttons. And I'll describe again what I've done in a second 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 can have age filter, year filter, 18 and say 25. So because we externalize that, we've got a generic filter now. Let me go describe what I've done here. The only difference is, so as we said before, we made this a generic filter. So it'll be filtered based on the column that's specified in the column definitions. We've made the title 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've got 18, 25 or off. And in year, we've got 24, 26, 28. So that's very specific. All that information is very specific to this custom filter I've made. You're unlikely to make a filter this specific, sorry, 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 pass here, unless there's 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 questions. Okay, I am Mohammed. I'll provide the link again. Hopefully you can see at 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 will be made available post-workshop. That's not a question I can answer. I think it is being recorded. So it will definitely be made available. How it's been 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 going to look at is states, because this is quite useful if you're having a custom filter. Make a sneaky sip of water. So in this filter, we're going to return, it needs to be an object, or it needs to be anything, actually, because when the set filters, a set model is called, it's going to be whatever you've provided. So that doesn't have to be in the format that our filters use. This can be anything. So let me demonstrate this. Because the filter you save, this filter components, whatever we save, this filter component will need to understand. So it kind of goes hand in hand. So if the filter states equals off, return undefined. So there is no filter state if the filter is off. Otherwise, return states filter state. So this may look a bit like certain states in
react components. It's not. This could be called anything. Okay. 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 call it a state in our use case. But whatever you save and return to the grid in 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, state model dot state. So what we've done here is that if there is no filter set, the model will be null and will set filter state to be off. Which again, just remind you, the filter state is off. The filter is not active. If a user has 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 here will be passed to the model. So in our case, if we've called 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 apply button and a clear button. We can use those buttons as we've done before, even though we're going to use a custom filter. So let's go back to our app, refresh it. So let's look at our custom filter. We're going to filter by 2004 and 18. And now if we save that, that's 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 we set 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 custom, the defaults provided filters divided by AG grid. But if you're doing your own custom filter, it's very simple to implement the model, 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 or 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 stay in sync without re-rendering? Who would own the grid state, row
data or Olympic winners? So when the
data is read from olympicwinners.json, the JSON file is immutable and the grid can't obviously change that. But the row
data is immutable. And 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 another 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 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 aggrid.com for docs on how to do that and that'll point you to repos for how to do that. But by default, the row
data that we use in the grid is mutable. So this
data here is mutable. 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. So this is true of any custom component. I'm going to describe it on how to do it on this filter component, but this what I'm going to describe now could be on any custom grid component, editor, filter, header component, filter component. You have certain use cases where 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 alert. 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 using pairs of handle. If you're using a class-based component, 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 so far, this isn't grid 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 made, we've exposed this, but we're not doing anything to it. Let's add a new button. Let's use this push me button, which we defined earlier. And let's use that. So we're going to use the grid
api, the grid.current.
api.getFilterInstance. Yeah. And then we're going to call back. I'll describe what I'm doing here. I'll just test it and then I'll walk you through what I've done. Push me. So my special filters, as you can see there on the top, I click 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 going to put in the grid, you can expose certain methods if you want to. It's not mandatory. It's just an optional thing. And what you expose can then be called. Firstly, you can get hold of the filter instances like this, getFilterInstance. You pass in the column you're interested in. That's the key. In this case, we're going to 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. 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 button to change in your filter or your editors or renderers to change color or set default or something. Either way, you can access your custom components by exposing them in using imperative handle. And then you can call them by using getFilterState here. And then you've got getEditorState and so on. GetEditorInstance and headerInstance. You've got all sorts of things. That's just a way to add custom functionality and be able to call that 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. There are others. There's about four or five others. I won't go into them, but what I will describe here is getModelAsString. And what this allows you to do is in string format, it converts 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 have the filter as a spinning wheel and then whatever value is chosen in the floating filter, you wanted to show a simple value. How you would do that is you implement getModelAsString, return whatever the model is as a string. So if filterState equals off, return an empty string, otherwise return the filter state. And then if we go to the column, we can say the low teen filter true. We don't have a filter, so that's 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 in 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 the filter. That's getModelAsString and that's most useful when you're going to use floating filters in conjunction with a custom filter. That's all I wanted to cover for today. We've overrun a bit. So by about 25 minutes. That's not too bad. I'll wait around on this and I'll check out Discord now just to see if there's any questions there. No questions on Discord. I think probably a few people had issues maybe joining Discord. 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. We've touched barely 5% of the grid 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 use Stack Overflow. If you're interested in acquiring a license or trying out AG Grid, contact email info at aggrid.com. Remember,
enterprise is free to trial. And if you don't want the console message or watermark, you can get a free trial key. Right. 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 road grouping. And set filter and multi-filter, the ones that are right out of the box. Only those three things, set filter, multi-filter, and road grouping are the only things that 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 full term, 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 azuregrid.com for more. Specifically for this workshop, set filter, multi-filter, and road grouping were the only things that were
enterprise. Everything else is available in the free
community edition. Three more minutes. Any more questions? Thanks, Michael. So if you're using, so if you're using yet states, use states and that sort of thing, the whole grid 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 edit, editable to be true, let me demonstrate this. So let's say that country, let's make country editable. And if we go to the browser, I would do X, the whole grid, so the cell value change and the underlying used row
data change, but not the whole grid. The whole grid won't re-render. Only that cell component will re-render. If you change all the row
data, the grid itself, the components 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 re-rendering 10,000 or say 1,000 new rows, of course the old rows will be destroyed and the new rows will be rendered, but if you're doing use
data like I've demonstrated here, 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 force it down and 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. All right, people, thank you everyone for joining. I'm going to sign off now. I hope you all have a good rest of the week and the weekend to come. Bye.