React Table Tutorial (TanStack Table)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's going on guys welcome back to another video today I'll be showing you how to build a complex table in react this table is going to have a lot of cool features like column resizing and custom cell inputs like this editable text field a custom status menu and a date picker I'm also going to add pagination so we can efficiently render large amounts of data we'll be able to sort by task and date and we'll also be able to filter by task name or the status I'll be using a library called tan stack table to build the table and then Chalker UI to style the components without further Ado let's get [Music] started I have the starter files open here and they're going to be linked in the description below if you guys want to follow along just make sure to run npm install and then npm run Dev to start the server right now we just have this heading and an empty task table and our entire app is wrapped by this Chalker provider with our our theme injected in our theme just has some basic config and Global Styles and these are the styles that we'll be used to style our table and the components within it I'm not really going to go over these too much cuz that's not the focus of the video but you can always refer back to this file if you want to know how the table styled so let's start building our task table as I mentioned we're going to be using the tanack table library and if you're not familiar with it it's a headless UI library for creating tables all that means is that it doesn't provide any pre-built components or any styling but it does give us a ton of helper functions to create manage and interact with our table but it's our job to create the UI that displays the table and interacts with it so the way we create a table is by calling a hook the name of that hook is called use react table and that comes from the tanac table library and that's going to return a table instance so we'll just capture that in a variable called table and this table is going to contain all of the helper functions that come from the library so we can see all these different methods that we can use to interact with the table we'll just store it in a variable called table for now as a parameter we need to pass it a few properties the first is a data property and this will be the data that is going to be displayed in our table I have a file here that contains all the data for our table and it's just an array with a bunch of objects and each object is going to represent a row which will have four different properties and these properties are going to be our columns so let's go ahead and import this data array in our table and we're going to want to store that data in state so let's call the used State hook we'll call the piece of State data and the initial value is going to be that data array that we just saw we're just going to import this real quick now that we have the data being passed into the table we need to add another property called columns and columns will be an array of column definitions so let's go ahead and create that array each column definition is just an object that configures the column we look at the docs we can see that the column definition takes an accessor key and an accessor key is basically just the key on the row object that's used to extract the value for that column so if we look at our data and this object is a row if we need to access the task then the key will be task if we want the status then the accessor key will be status so let's go ahead and add the accessor key and for the First Column it was task and now the next property I want to add is the header if we go back to the docs we could see that the header takes either a string or a function that returns a react component this header property really just refers to the header for each column in our case we could just use a string because we don't need anything complicated for this header so let's go back and add our header value and we could just call that task and then the next property we need is the cell and the cell is going to refer to each individual cell for the row for the cell we're going to need to pass a custom react component for each column if we go back to the docs we could see that the cell takes a function and as a parameter it gets this props object and within our component we can have access to the table the row the column and a few helper functions so let's go back and add our cell and the most basic cell we could add is just a function that returns some jsx so we'll just return a paragraph and inside we want to call the get value function so we'll take in the props here and we could call the get value function that we just saw in the docs so we'll do props dog value and this will just render the value as it is on the row object now let's create the rest of the columns so I'm just going to copy and paste this and since we have four properties here we need four column definitions and I'm just going to split this as we create the rest now the next property is called status so I'll change the accessor key to status and the header to just status and for now we'll keep the cell like this and then we need to change the due date and lastly the notes now that we've created all the column definitions let's go ahead and add the next property and that's called get core row model the value will be get core row model invoked and this is a method that comes from the tanack library so make sure you import it this would just basically allow the row model to work under the hood within the react table library and these are all the props that we need to get started so let's go ahead and create our table container so it'll be a box with a class name of table and now we want to render out the headers for the table the way that we can get access to that is by calling the get header groups on the table so we'll just log table. get header groups and let's just see what that looks like we could see that it's an array of header groups in our case we just have one header group and that has a property called headers and each header item here has a column property within that column property it has the column def property and this refers to the column definitions we set up right here and the value that we're interested in is this header property so it's pretty nested deep but our goal is to map through each header in this array and output that deeply nested header property so let's go back in our code and output the headers let's start by calling table. get header groups and then we're going to map through the header groups and for each header group we want to return another box and we want to give that a class name of table row or TR and we'll give it a key of header group. ID now inside each header group we want to map through the headers array so we'll do header group. headers do map and for each header we want to Output another box and we'll give that a class name of th and we'll also give it a key of header. ID and here's where we're going to Output that string so we can call header. column do column def. header and this will actually render out this header that we defined so if we hit save we should be able to see those headers on the table and there they are now let's output the rows to do that we need to call table. getet row model and then we need to access the row property and we're going to map through each row and for each row we're going to return a box once again we'll give the Box a class name of TR and a key of row. ID and now within each row we need to render out the cells so we'll call row dot get visible cells and then we're going to map through through each cell and output a box we'll give the Box a class name of TD and a key of cell. ID and now instead of doing something like this to render out the cell value we have to actually call another function called Flex render and the reason for that is if we look back at the column definition and the header property you could see that it's just a string so for the header it's all just strings and we could render that out but for the cell property it's not a string it's actually a react component and the way that we render react components and enable them to get these props injected in is to call the flex render method that's a function that comes from the tanac library and we could just import it at the top and we can see the first parameter is the component and the second parameter is the props so in order to get access to the component we need to write cell. column. column Def and then do cell and all we're really doing is getting the column definition which is one of these and then accessing the cell property which would be this react component the second parameter is the props and the way that we can inject the props is to call cell. get context and now if we save this we should see all of our rows displayed and we're getting an error and the reason for that is because in our status definition for the cell property we're outputting props doget value if we look at the status the value is actually this object and we can't just output an object to the screen instead we should output the name so let's go back and do props doget value and we'll just add name and sometimes there isn't a status like here so we'll just add a question mark here to only access the name if it exists now we have to do the same thing for the date because the due date is an actual date object and we can't render that out to the screen so we'll just check if the value exists and call to local time string now if we save we should see those errors go away the errors are gone but our table still looks terrible that's because I forgot to add the width to our components so we want to add the width property and we'll make it equal to table. get total size and for the th we also want to set the width property equal to header. getet size and lastly for the TD we want to also set the width to cell. column. getet size and now our table should look normal if I wanted to change the size of each column I could go back to the column definitions and add a size property I'll set it to 50 pixels and if we hit save you'll see that the column shink to 50 pixels now ideally we'd want to set a default size and then allow the user to resize the column dynamically if we look at the finished product we'll see that the user can resize the column to be whatever width they want so let's start working on that feature the way that this will work is we need to create this Sizer bar and this is just going to be a div that's absolutely positioned on this header cell and by default it will have its opacity set to zero but once you hover over the header cell the opacity will be set to one so let's go ahead and create this resizer div right after we display the header value we'll create the div so we need to give it a class name of resizer if we hit save we should be able to see that resizer bar and there it is if we open up the Styles file we can see that this resizer class has a few CSS properties it's positioned absolutely and has an opacity of zero and this CSS selector is basically saying that any element that's hovered and has a child with the class name of resizer it will set the resizer opacity to one and that's how it's displaying we also have this selector which checks if the resizer also has the is resizing class if that's the case it'll change the background color of the resizer div to green and also set the opacity to one now this class will be set on the resizer anytime the column is resized and that's all handled by the tan stack table Library so we just need to add the necessary props to make it all work let's go back to the resizer component and instead of having this be a string let's make it a template wial We'll add the resizer class and now we have to check if the Callum colum is being resized and if it is we need to add that is resizing class right here so we can check if the column's being resized by a helpful utility function from the tanack library and it's called header. col. getet is resizing and this is going to return a Boolean and we want to check if that's true we want to Output that class name is resizing otherwise just output an empty string so now only when the column is being resized it's going to add this class name and change the color to Green now we need to add two more props to it the first is on Mouse down and this is going to be equal to another utility function from tan stack library and it's going to be header. getet resize Handler and this will just return a function that will handle all the resizing and we also want to add on touch start that's that's going to be equal to header. getet resize Handler as well now the last thing we need to do is go back up to our table configuration and add the column resize mode and that's going to be a string of onchange and that's basically going to resize the column as we change it and drag it around as opposed to when we let go of the mouse so if we hit save and go back here it should all work properly and if we were to change this to on end you could see how that works and that just basically resizes the column and you drop the cursor we'll change this back and now we could start working on this first text input let's begin by first increasing the size of the task input to something like 225 and instead of returning this paragraph for the cell let's create our own custom component that will have the editable input and will update the table state so under components let's create a new file and call it editable cell and let's start building out this component the way that this is going to work is each task cell is going to be an input with its own local state once you type in the state and you blur it it will then update the overall table State let's first begin by creating this input with its vocal state in this return value we want to return return an input and that's going to come from Chakra and then I'm going to paste in some Styles and now we need to hook up this input to some local state let's call the used State hook and we'll store the state in a variable called value and the default value will just be an empty string now let's hook up our input to this state so we'll set the value equal to our state value and the onchange fun function we'll take in the event and call set value passing in the event. target. value let's make sure to import the used State hook and also make sure the input is self-closing now if we save we should be able to use this editable cell in our column definition let's get rid of this function and paste in the editable cell import that and if we hit save now we see this input and we could type in the local state and it works now we need to initialize the input with whatever the value is for the row because right now initially all the inputs are empty so we can do that by using one of the helpful utility functions from tanack if you're remember from the docs this cell gets past all these properties and the method that we're interested in is get value so we can go ahead and destructure get value and we can capture the return value of that so we'll say initial value is equal to get value invoked and then we'll pass in the initial value to our state so now if we hit save all the inputs should be initialized with the value the next thing we want to do is ensure that our local state here is in sync with the outer table state so let's call the use effect hook and we're going to pass in a function which is only going to run when the initial value changes and what it's going to do is update our local state so we'll call set value and we'll set it to whatever the initial value is the last thing we need to do is update our overall table State once we blur the input because right now all of this state is only being changed locally and you can see that by going back to the table and logging the data we go back and open up the console you'll see here's all the data and and if we update this add new feature task you'll see that it never actually gets updated here so we need a way to update this data for the table through our editable cell the way that we're going to do that is add a meta property on the table configuration this meta property is going to contain metad dat on the table that will be accessible through our custom cells so we need to create a function that will update this data we'll call the function update data and we're going to need to pass in three params if we look back at our data State it's an array of rows so we first need to know which row we need to update the index of the row once we have that we need to know which column to update in our case that's task and then we also need the new value to update it to so let's take in those three values we'll get the row index the column ID and the value then we're going to call set data we'll get the previous data as a property and we want to return a new array with the updated data so we'll call previous do map and we're going to map through each row and the index of that row and then we want to check if the current index that we're mapping through is equal to the row index that was passed in which means this is the row that we need to update so if that's true we're going to update it otherwise we're just going to return the row now we need to spread the previous properties of the row so we'll do previous of the row index and now we need to set the new value and this column ID will be the property that we need to set so we can open up square brackets and add the column ID and we want to set it to the value that was passed in so again to reiterate we're mapping through the previous data and we're checking for the current Row in the loop and if that current row is equal to the row index that's passed in from our cell then we want to set it to this object which will spread the old values and override the new value otherwise we'll just return the old row now that we have this function we need to call it from inside our editable cell in the props we get access to the row itself the column and also the table now let's create our blur function that's going to call this update data meta function so we'll say const on blur is equal to a function and we're going to call the table. options. meta to get access to that meta property we'll check if it exists and if it does we'll call update data so now this function will be what we defined here and so we need to pass in these three parameters we have access to those through the props to pass the row index we could do row. index for the column ID we could do column. ID and for the value we just want to send the value in our state now let's use this on blur function in our input and this should update the table state so if we add a few exclamation points we'll see in our state it gets updated there so now our table is in sync with each local input so that wraps it up for the editable input let's start working on the status input we'll start by creating a new file under components we'll call it status cell and in the props we're going to want to destructure these same properties and instead of this div we're going to want to return a chakra menu so if we open up up their docs and go to the first basic example we just want to copy all of that and paste it in and then import all these components now for the menu we want to add a few props We'll add is lazy and that will just prevent all these items from rendering unless the menu is open we also want to set the offset and that'll just position the menu we want to set flip to false and Auto Select false for the menu button I'm going to get rid of these props and just paste some new ones in instead of actions I'll just change this to status for now and let's just confirm that this menu is working so we'll go back to our column definition and get rid of this function paste in our status cell and we should see that new menu and there it is it's working now let's replace this status with the actual status of that row we can get the status of the current row by calling get value and that's going to return the object in our data so something like this so let's destructure the properties we'll grab the name and the color and sometimes the status is null so we'll just default it to an empty object now instead of status let's just output the name here and for the background color of this button I want it to be the color of the status so we'll set the BG equal to the color and if it doesn't have a color we'll default it to transparent and lastly I'll set the text color to gray. 900 now we should see that status and it looks like they're showing up correctly now let's work on these menu options instead of using these these values we want to Loop through our own custom statuses that we've defined if you open up the data file you'll see that we have an array of all the statuses that we want in our app so let's just go ahead and copy that over and make sure to import it we're going to map through each status and then we want to return a menu item for the value we'll just output status. name and then we want to add some props to the it first we'll give it the onclick Handler and we want that to be the function that updates our table state so first we need to grab that update data method that we defined in the meta so let's come up here and just do const update data and we're going to get that from The table. options. Meta now let's go ahead and use that down here so we'll set this equal to a function that's going to call update data and then we'll pass in the same three params as before so row. index column. ID and the value we want to set it to is the current status That We're looping through so this will be an object that has the ID name and color and then we also want to add a key to the item so we'll set that to status. ID and then let's remove these old items and now we should see the menu with our own custom statuses the last thing we have to add is the little color icon so let's go ahead and create that icon above we'll do cons color icon is equal to a function that's going to take a color prop and then we'll grab the rest of the props if any were passed and we're just going to return a div then we want to add some properties to it to style it I'm just going to paste those in real quick so we're just giving it a width and height setting the background color and giving a border radius now let's go ahead and use that in front of our name and we want to pass it a color prop and that's going to be equal to the current status. color so now if we save we should see that and there we go now let's just add some margin right and those should be good and now if we change it it should actually update our table there we go and the last thing I want to do is add an option to clear the status so we'll just take one of these menu items and add it above and for the name we'll just do none and for the color we'll just do red. 400 it doesn't need a key and for the update data function instead of passing in a status we'll just set it to null so now we should be able to clear a status and there we go go now let's start working on this date picker let's begin by creating a new file we'll call it date cell we're going to be using a npm package to build our date picker and it's called react date picker so if we just scroll down to the example we need to copy these Imports and we're going to need to destructure the same props as the other components so I'm just copy these over and we're also going to need these two lines so we'll copy those over as well now instead of returning this div we want to return the react date picker that we imported at the top and this date picker takes some props the first one we want to pass is the wrapper class name and I'll call that date wrapper and there are some styles that are going to apply and then we also want to pass the date format we'll give it three M's and a D next we want to pass the selected prop and this is going to refer to the date that's selected in our case we want to set that to the date that is on our row so this do property and since we're getting that value up here we can just set that to date and then we could pass that in down here and let's remove this default value of an object if there's no date it's fine to just leave it as null the next property we want to add is the onchange function and this is going to run anytime the user selects a date so we'll pass a function and we get the date that they selected as a parameter and then we want to call the update data function we'll pass in the same parameters as before so row. index column. ID and for the value we'll just pass the date that they selected so now let's use this in our column definition we'll remove this function and pass in our date cell so now we should be able to see that input here and when we change a date it should be reflected in that cell now let's start styling this input we can tell the date picker to use a custom component to render our date we just have to pass the custom input prop and this will take a react component as a value so let's go ahead and create that component above we'll call it date custom input and we want to destructure some props so we want to grab the value and the onclick function and this is going to come from the date picker library then we want to return some jsx we'll return a center and this will refer to our cell whenever the cell is clicked we want to run the onclick function and that will take care of opening up the date picker we also want to pass it some style props so we'll set the cursor to pointer for the children we want to want to check if a value exists so if there's a current date then we want to Output a fragment otherwise we want to return the calendar icon if we look at the finished example you'll see that if there's a date it renders it out otherwise it has this calendar icon so let's go and add that calendar icon and then we'll set the font size to excel now if there's a value we're just going to Output that value now let's go ahead and pass this to the custom input and in order for this to render properly we need to wrap the component in the forward ref function and that comes from react and we'll just wrap the entire component the first parameter will be the properties that we want to pass and then the second one is the ref and we're just going to set the ref on that Center component now if we save we should see our custom input and there it is the last thing we need to do is add the little X icon to clear the date so if there's a value we want to Output that value but then we also want to add that little icon so right after the value that we output let's add a box for the child we want to Output the time symbol and then I'm going to paste in some style props the next thing we need to do is clear the date when a user clicks on this box so let's create the onclick function the way that this will work is we need to pass a function to the custom input that will clear the date when you click on it so let's define that function and we could call it clear date and let's pass a function that's going to call update data and we'll pass in the same three params as before row. index column. ID and since we're clearing the date we want to pass null now we could take this clear date function and destructure it in our props and we could call it down here in our onclick Handler so if we hit save and go back to our app we should see that X but you see when we click the X it actually opens up the date picker and in order to fix that let's take in the event and then call event. stop propagation and this will prevent the event from going onto its parent which is this Center div which calls this onclick function so by stopping the event it never reaches this click Handler so now when we click it it should work as expected that wraps it up for the date picker and I just realized that we forgot to update this notes column so let's go ahead and paste in that editable cell from the task input now that should look normal now let's begin by creating these filters but first let's look at the docs to see how we can implement this so all we need to do is create a filter state that we pass to our table and then our table knows to only show the rows that match that filter if we look at the filter state it has a column filters property and that's equal to an array of column filter objects each column filter object is going to have an ID and a value this will refer to the column ID and the value will be the value that we want to use to filter by in our case that's whatever the user input in the text box so let's go ahead and create our filter state right below our data State let's add our column filter State and we'll call it column filters that's going to be equal to use state and the default state will be an empty array which means there's no filters and to pass this state to our table we need to add a property called State and anything we Define inside this state object will be accessible through the table utility functions like table. getstate so we can call that function through other components now that we're passing that to the table we need to create the filter components that actually have the input so under components let's create a file called filters we'll swap out this div for a box let's create an input group and we're going to pass some style props to it we'll set the size to small and give it a Max width of 12 REM then inside we want to add an input left element and we'll set the pointer events to none and this is going to be an icon and we want to use the search icon and then below that let's add our actual input I'm going to paste in some Styles real quick now let's import our filters on our table We'll add it right above the table and we should see it now right above there let's add some bottom margin first we also need to add a new property called get filtered row model and that's going to be equal to get filtered row model invoked and that's a function that comes from the tan stack library and this will just make all the magic behind filtering work now we need to hook up this input to our table filter state to show you how this is going to work I'm just going to create a filter object we'll set the ID to task because that's the column we want to filter by and for the value we're just going to pass in a string to filter by so now if we look at our tasks they're filtered by this ad so what we need to do is when a user types in this input we need to create an object with the ID of task and the value to be whatever they typed in so we could delete this for now and let's pass in these properties to our filter component now we could go and destructure that now let's grab the filter value that comes from our column filter state so we'll do const task name it's equal to column filters doind now in here we want to look for a filter object that has the ID of task because that's the column that we want to filter by so for every filter let's check if the filter. ID is equal to task and if it finds an object with that ID of task we want to grab the value property on it otherwise we'll default it to an empty string now let's pass this task name in for the input value next we need to add the onchange function so whenever the user types in the input we need to call the set column filters function to add that object to our column filters array so let's create a function up here we'll call it on filter change and this will be a function that takes in the ID which is the column idid and the value and this function is going to call set column filters now we want to remove any previous task filters and concatenate a new filter object with the current state of the input we can do that by getting the previous state and returning a new array we want to remove any objects that have the ID that matches the filter so in our case that's task so we'll do previous do filter for each object we only want to return the filters that don't have the ID of task and then once those are filtered out we want to call the concat method and add a new object with the ID that was passed in and the value that was also passed in so these properties here now we can call this on filter change function down here so we'll grab the event and then call on filter change we'll pass in task as the column ID and for the value we'll get the event. target. Val now if we save and log our column filter State we should see that new object being set and here it is we'll see that our column filter array has an object and the ID is Task and the value is the value of the input and now our table is actually being filtered now let's work on adding this status filter under components let's create a new file called filter popover for this component we want to return a chakra popover so if we go to their docs and scroll down to the first basic example this is what we'll use as a starter so we'll copy that and paste it in here and then import all these components we can remove the header we'll want to add the isy prop to the popover for the button we'll give it a size of small and a left icon of the filter icon and we'll set the font size to 18 and instead of trigger we'll just call it filter and we can remove this body and paste in some text inputs so we'll have filter by and then the status and right below the the status we want to Loop through each status in our array and output a div first we'll create a vertical stack to space them properly we'll set the Align to flex start and we'll give a spacing of one and in here we want to map through each status and return a status item and we're going to create this component in a second but we're going to pass the status in the props and also give it a key we'll set that to status. ID now let's create the box that renders each status so con status item we're going to destructure the status in the props and we're going to return a flex component which is just a flex box I'm going to paste in some Styles real quick and for the children we want to Output the status. name and we also want to grab that color icon icon from the status cell we want to export this color icon and I'll just grab the same one here paste that in and import it at the top and now we can import this filter popover in our filters component we'll put it right below the input group and we should see that filter pop over and there it is and in order for this to display horizontally we need to change this from a box to be a horizontal stack and we'll give it some spacing and these should be aligned properly now let's start adding the filter functionality so when a user clicks on a status icon we should create a column filter object and the value will be an array of the status ID that was clicked and if user clicks another status that status ID will be added to that value array so let's let's go back to our filter popover and on the status item let's add an onclick Handler this is going to be a function and when it's clicked we want to update the table column filter state so let's hop into our filters and pass these properties into our popover now we could destructure them here then we could pass set column filters to each status item now in the status item we could destructure that function and call it in here for now let's just pass an array with one status filter we'll set the ID to status and the value is going to be an array of one and we'll just hardcode this for now if we go back to our table and we click on a status you'll see our filters array now has the status filter object and the value is an array of a status ID now we need to refactor this to pass the actual status ID and then also handle multiple statuses and let's remove this for now we also don't need these curly braces and now in the set column filters we're going to get the previous filters and we want to check if there are any active status filters so we could do con statuses equals previous doind so we're going to look through the array of filters and for each filter we're going to check if the filter. ID is equal to status and if we find one we want to grab the value property and remember this is going to be an array of status IDs and we'll do a quick check if there are no statuses then we're going to return the previous filters and conc catenate a new filter object we'll set the ID to status and the value will just be an array with the first status filter and we need to pass the ID so we'll do status. ID so now if there are no statuses we're just going to return all the filters with this new object added on which will have the status ID of the one that was clicked so now if we hit save and we have one filter here we'll see that in the state but then we also click a status we'll see that we have two filter objects one is for the task and one is for the status and in our status our value looks correct now let's work on adding multiple statuses so if we make it past this if check that means that there was already a status filter that was active so now we want to return the previous filters and we're going to map through each one one and for each filter we're going to check if the filter. ID is equal to status if this is the case then this is the filter object that we want to update otherwise we'll just return the filter now in this object that we want to update we first want to spread the old filter and for the value we need to either add a new ID to the array or remove it if it was already active so we need to do something like is active and if that's true then we want to filter out the status but if the filter is not active and it was clicked then we want to concatenate the status ID first let's filter out the status if it is active so we'll do statuses. filter and we only want to keep the status IDs that don't match the one that was clicked so we'll do status does not equal status. ID and this would be the ID of the stat status that was clicked if the status was not active then we want to add it to the array so we'll do statuses. concat and we'll just pass in status ID so now if the status was previously active it'll be removed from the array otherwise it'll be added to the array now let's work on the logic for this is active flag the way that we can figure out if any status is active is to First grab the array of all the active statuses we'll do const filter statuses and that's going to be equal to colum filters. find and we want to find the filter that has an ID of status if that's found we want to get the value property which will be the array of status IDs and if that's not found we'll default it to an empty array so now we can use this to see if the current status item that we're mapping through is is included in this array and if it is then it means that it's active so we'll add the prop is active and that's going to be equal to filter statuses do includes and then we'll pass in the status. ID we just need to destructure this is active flag and it should work properly let's go back to our table and select a status we'll see that the ID is in the array and if we click it again it should get removed and now our array is empty and let's check that we could add multiple statuses so I just added two and we should see two different IDs and there we go now let's work on displaying the status in an active state if it's selected in the status item let's add a BG property and let's check if it's active we'll give it a background color of gray. 800 otherwise it'll be transparent now we'll see that they're displayed in an active State and if we remove it it goes away now let's work on actually filtering the rows by status to do that we have to update our column definitions so let's find the status definition and we need to add a few new properties the first one is enable column filter we're going to set that to true the second property is a filter function and this can either be a string or a function that returns a Boolean which will tell the table whether to render the row or not so if we look at the docs the values for the filter function can either be a string which will use one of the built-in functions from tan stack so for example we could set it to include string and that will only filter out rows by this condition or we could pass it a function and that function will get a number of properties it will get the row the column ID and the filter value so we can use these properties to determine whether the row should be rendered or not let's go back to our definitions and if we wanted to be explicit we should add this to our task cell this worked before without these properties because there are some defaults that the library used to filter by but we should set these properties we'll use the built-in function called include string and for our status filter we want to add a custom function and this function is going to take a few parameters so we're going to get the row the column ID and the filter value and we'll just call it filter statuses because that's a bit more specific now this function needs to return a Boolean if it returns true then the row will be kept if it returns false then it'll be removed first let's grab the status of the current row that's being evaluated so we'll do con status equals row. getet value and remember in our data this object is a row so when we call get value we need to pass in a column ID in our case we want status so we'll pass in column ID and since we're in the status column this will be that string now status will be either the status object or null if it doesn't have a status and we want to return filter statuses and remember this is going to be the array of status IDs that are defined in our status filter right here so we want to check that array and see if it includes the status ID being evaluated this status could be null so we'll just add a question mark and now if we save the filter should work so we'll select on Deck only that status is displayed and then we'll add in progress and that works and if we add a third filter that should also work however if we start removing these filters you'll see see that when we have no filters the table doesn't display any rows and the reason for that is our filter value is an empty array so our filter function when it does this check the status being evaluated will never be true because it's never going to be in an empty array so we just need to add a little check at the top we'll do if filter statuses. length is zero meaning there are no active statuses then we'll return true meaning we should keep the row in the data so now if we go ahead and refresh add a filter and then remove it the table goes back to normal that wraps up the filtering now let's work on the Sorting functionality to begin we need to add a new property to our react table that's called get sorted row model and again in order for sorting to work we need to invoke this function which comes from the tan stack library now we can add our sort icon on in our table header so let's find our th and right below the header that we output let's open up curly braces and we can use a helpful utility function to check if the column can be sorted so we'll do header. column. getet can sort and this function is going to return a Boolean so if this is true We'll add the double Amper sand and we want to Output an icon only if the column is sortable we'll output this icon and we want to use the sort icon we'll give it some margin font size will be 14 and lastly we want to add an onclick Handler for the onclick Handler we can use another helpful utility function we'll call header. column. getet toggle sorting Handler and this function is going to return another function that will handle all the logic behind the scenes to get sorting to work so now if we save we should be able to sort by the column colums and that seems to be working by default all the columns are sortable unless we explicitly disable that feature in the column definition so for the status it doesn't have a great default sort so let's go ahead and disable that we go up to the status column definition we can add another property called enable sorting and we'll set that to false and now that icon won't displayed because this helper utility function get can sort will return false for that column the next thing I want to do is add a little indicator icon which will tell the user whether the sort is ascending or descending we can do that using another utility function from tan stack so let's just call header. column. getet is sorted and let's just see see what this returns you'll see that it's either ascending or descending and if there's no sort then it's just empty so let's output that icon so we can create an object and add those two cases ascending if it is ascending we're going to return this icon and if it's descending we'll return this icon and off of this object we want to access it so we'll open up the square brackets and then we'll just paste in this utility function in the square brackets this function will either return ascending or descending and therefore it'll grab the string value and output it if it doesn't find these properties then it'll output undefined if we save this now we should see that indicator that wraps up sorting if you guys wanted to sort by the status you'll have to pass a custom sorting function in the colum definition similar to how we add a custom filter function but I won't be going over that in this video the the last thing we need to add is pagination let's begin by adding these inputs in order to get pagination working we need to update our table configuration let's pass a new prop called get pagination row model and again we have to invoke that from the tanack library and now we'll be able to use the pagination utility functions right after this box here which is the end of our table component let's create a text input now we're going to use two utility functions the first one is table. getet State and then we want to access the pagination state and get the page index and we'll see what that returns and the second function is table. getet page count so if we just look at what this returns you'll see Zero and one zero is the index of the page page and we want to just add one to it to get the actual page number and then this one is the total Pages by default the pagination state renders 10 rows and since we have less than 10 there's only one page so we'll add a few more rows to test the pagination let's make this a bit more human readable so we'll say page and then this value that we want to add of with the space and then let's add one to the page index so now that should be a a little bit more human readable let's also add a break above this text just to add some spacing and then in our data I'm going to add a few more tasks so we can test the pagination so if I save this then we'll see page one out of three now let's add these buttons to navigate between the pages let's go below our text input and output a button group in here here we'll want to add two buttons one for the previous page and one for the next page now let's add the onclick handlers for the buttons let's pass a function and we want to call table. previous page we also want to add an is disabled prop we want to check if the table has a previous page so we could do table. get can previous page that's also a function and we just want to check if it's false so if it can't get the previous page then this button will be disabled now let's do the same thing for the next page button this time we want to call table. next page and we'll just copy this is disabled prop and change this to get can next page so now our pagination should be working and there we go if you guys want to customize the pagination behavior like only output three rows instead of 10 you'll have to add pagination state to the table for example you'll add a new property here called pagination and if you look at the docs on pagination you'll see that this pagination state takes two properties the page index and the page size the page size will refer to how many rows it displays per page and the page index is which page you're currently viewing so if we add the page size and set it to three and set the page index to zero you'll see that now only displac three rows with this method however we have to manage updating the state because these buttons no longer work using the built-in utility functions we would have to store this pagination in some state above here and pass that in like we're doing with the column filters so that's a bit more work but I just wanted to show you guys how to do that if you were interested in that that wraps it up for this video thank you guys so much for watching leave a like if you enjoyed And subscribe if you haven't already it would help me out a ton let me know in the comments if you have any feedback or what you guys want to see next and I'll see you in the next [Music] one
Info
Channel: Nikita Dev
Views: 32,396
Rating: undefined out of 5
Keywords: javascript, react, react tutorial, react table, tanstack table, javascript tutorial, react js, react hooks, react state
Id: CjqG277Hmgg
Channel Id: undefined
Length: 60min 17sec (3617 seconds)
Published: Sat Sep 16 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.