NextUI Table Component in NextJs

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey friends welcome back to the channel in this video we're going to implement a user table using the next UI Library we're going to start from a simple table then we're going to add pagination filters and sorting so as you can see here we have pagination uh we can filter by a specific name uh it filters only the name and we can also sort uh once we filtered or even when we not filtered so we're going to build on on top of a project we have done previously on the channel where we implemented next UI in our nextjs app if you haven't watched that video we implemented this little card component and also talked about different theming options that comes built in with next UI you can change the colors the border radiuses and whatnot if you haven't seen that video I'm going to include a link in the cart suver so you can watch that to understand how you go about bringing next UI or installing next UI U into your nextjs application in this video we're just going to build on top of that one and create a table component for users to render some users all I have done on top of that project is to create this uh users page or segment or route and put a page. TSX inside of it and as you can see here this component is responsible for rendering our users so going back to next UI documentation we're going to start from a simple table component and then we're going to add features like pagination sorting and filter as we move on so let's us start by this first simple table here as an example if you click on the code tab you'd be able to see the code for this let's just copy this come back to our app and let's create a component called user table TSX and let's just copy paste the code that we have over here now as you can see the next UI package exposes different components when it comes to tables for Heather for columns rows and cells you're rendering a header here with bunch of columns and a table body with bunch of rows and inside each row we have cells so let's rename this to our user table and let's also get rid of this react import Also let's use the use client directive because this is a client component let's go back to our page and bring in our user table to this page and let me just get rid of this heading and now if I go back to my component and refresh we should be able to see that same simple table so pretty straightforward you can use this uh components exposed from next UI to shape in simple tables but often times this data is not like this static and it will be dynamic so in the next example let's actually see how we would deal with Dynamic data so let's fetch some users inside our server component and then pass those users as our data to our table now here it says to render tables dynamically you can passing the columns prop to your header and the items prop to your table body so let's see the implementation here I'm just going to click on the code again and let's just copy this code and replace this again with our component here I'm going to explain what we are doing let's just rename this to user table first so here uh we're pretending that instead of having the row statically hardcoded inside of the table we are having these rows and columns and we passing this to our table component so as I mentioned passing the columns to the table header and then having a render function or render prop here that takes every column and for each column it's going to render a table column component from next UI and it's going to render the label of that column now our columns here as you can see has a key and a label okay we're going to move this columns definition in a second but from a high level that's what that's how you would render your columns now similarly for the rows or for your data we're passing in the items prop to the table body for each item we receiving this render prop or receiving the item inside the render prop for each item or row inside of our data we are rendering a table row and inside each row we are getting another render prop which receives this specific column key we're going to then use this get key value again from the next UI library to get this specific cell data from that items object so from that specific user let's say and then we're getting a specific key inside of that user object to then fill in different cells inside of our row so if I save this and actually uh set the use client directive up top the same way that we did for the previous example and go back to our app we should again see that same table but the only difference is that we are actually using these props to pass in our columns and our data so let's actually make this really Dynamic by passing in our user data instead of having to hard code this whatever object or whatever data we have over here now the first thing that what I want to do is inside of our users I want to create this column component where I can actually export these columns and uh other useful data for my table inside of this file so we're exporting that column let's actually also Define our users shape so the user that we're going to be fetching in a second has this shape there's an ID name email image and a last scene property and we have this column definition First Column is name second second column is going to be let's say email and then the label will be email and then the last column maybe we can have the last scene property and then the label is going to be last scene okay going back here so let's just export this columns and now for the rows let's actually fetch some data service side and then pass that data to our user table let me close this off so we have more room let me paste in a function that allows me to fetch some users I have a typo here so let's rename this column to columns yes let's also update the import now I have defined this get users function which returns a promise that resolves into an array of users you're hitting this uh mock API endpoint which is just going to give us back some users and we're returning the users so from here inside of our app we can say users and now we can evate this get user get users function we created to get some users again we are inside of our server component so we can turn our component or page component into an async function therefore we can evate or do the data fetching right inside of our server component now before I go ahead let's just open up this mock API site I've talked about it before but it's mock api. you can create different projects and different endpoints inside of each one you can Define uh shapes or schemas for the resources that you want to fetch you can also connect different connected resources so for example users and to-dos and then it exposes an API endpoint for you to just fetch them inside of your app when you are testing or during development coming back to our application so all did is to fetch some users here now let's pass this users down to our user table so we're going to expect a users prop here so let's go to our users table and actually expect this props of users can also type this to be users and this is going to be again an array of user okay now that we have this users this this is going to be our data so instead of passing in this rows I can pass in my users here and say for each item I'm going to access item. ID because my user has an ID and then pass that item and the column key to this get key value to render each cell now on the right hand side as you can see it populated my table because I have already defined my columns to be name email and last scene this is coming from our definition of columns and then inside of our user table we basically are mapping over our data for each user object we are creating a row inside of each row we are creating different cells by calling this get key value function that provides the user object and that specific column key which maps to this column Keys here to render that specific cells data so now this table is no longer using this static data it's just dynamically fetching data inside of our react server component passing it down to our user table which is a client component and we're rendering that dynamically here so let's go back to the documentation and move to the next step now one thing I want to mention is this little note that they have here uh you may wonder if you have an array of users what are we not mapping as we usually do in react components uh to render each row and it's explaining that for react ARA to be able to actually render this items inside your table efficiently it's better to use this items prop and reactar is going to Cache uh this data or list items so therefore it's not going to rerender every item when they change this is a performance optimization technique rather than using the array. map now when we are dealing with empty state so when we don't have any users we can actually pass in a prop to our table body as you can see empty content and say if there was nothing here just render this so if I go to table body and actually paste this in here to say no rows or no users to display if I go back inside of my page component now and pass in an empty array coming back to our page and refreshing we see this no user to display pretty straightforward now without Heather is if you don't want to have a header without wrapper is without that wrapper that we can see around the table um and now next let's talk about custom cells so instead of just rendering the username it's showing the name the Avatar and also to email in one cell and then there's different things you can do for each cell let's now see how we would go about implementing this now here in the code example what they've done is theyve created this render cell function where it gets the user object and this specific column key that VI are on and it's going to use a switch statement or it's going to check to see what the column key is and depending on the key it's going to return a component to be rendered inside of our cell now inside of our table instead of calling the get key value we calling this render cell passing in the item or the user object and the specific column key now I would like to take this function out of this component or the table component and actually put it inside of our columns where we're defining our user table object so let's actually copy some code and I'm going to explain what I'm doing here we would also need some icons so let me just quickly copy these icons as well so we have this icons component that's basically exporting a couple of different icons as you can see we're going to use them inside of here so let's actually see what we're doing so I'm creating that same render cell function that we just saw on the docs uh which is going to get the user object and the column key we're going to get the cell value by accessing the user object at that specific key and then we switching on the column key if it's the name we're going to render a user component this is also from next UI if I go back here let me just make this a smaller on the left hand side you can actually see different components from next UI now down in the bottom there's this user component which basically is a combination of the user Avatar the name and a description that you can pass in there so for the Avatar I'm using the image key or property on the user object for the description I'm using the email for the name I'm using this cell value because remember we're on the key of name so this is going to be U the name of our user now before going to the next key I also want to mention that I have changed the column definition so before we had the name the email and the last scene now here because I'm already showing the email inside of this name column so I've changed I've removed that email column on its own I put this last scene and then at the end we're going to create this actions column where you can have different buttons to edit the user to view the user or to delete the user so the next column or the next key I'm looking up is the last scene if that's the cell we are rendering I want to get the cell value turn it into a new date and then change it to the local date string which is a better representation of our date and inside of our actions column this is a column that's not actually using the cell value it's just rendering some tool tips but you can actually also access the cell or the specific user object here to then perform any action that you want for example editing or deleting the user so going back inside of our table now instead of calling this get value the let's actually call our render cell that we just created that is going to now return some custom cells for us so let's go back to our application if I go back to the page and replace this empty array with our users and save now as you can see we have changed how our table looks we've customized the name colum to actually show a user component with the Avatar name and email we also formatting this date into a local string and we added this actions column where you can actually perform different actions on this specific user now if you're fetching 100 users and all of them are showing on the same page so next let's actually Implement pagination let's go to the table Tab and here let's search for pagination let me close this off so let's look at paginating our table so again let's look at the code here so what they've done is they are creating a local state to store what page we're currently on and then we're getting the length of our users or the total number of our users divided by how many users per page we want to show to actually come up with our total page number we then are going to actually slice our users array with an start and end that we're calculating in depending on the page so whatever page you're on this is how you would calculate the starting and ending index of your users so page minus one times the number of users per page and then at the end it will be your start plus uh the number of users per page and anytime our page changes we're going to actually reslice our users array to then show that specific number of users now down here in the table uh what they had done is also included this bottom content on the table component where you can pass in an actual component they are using this pagination component from uh next UI so again if you look at this pagination you can see that they have this pagination component with different options that you can use so going back here let's actually implement this together so inside of our user table what we want to do is actually bring in this piece of state so let's copy this inside of our component we're going to need the user state so let's import this from react let me also remove this and bring in use memo now the use memo is not very useful when we just using it on its own here but later on when we are actually implementing sorting and filter we're going to use the value of this items inside the dependency arrays of other functions that's why we memorizing this function to not recreate it or to not cause a render in other functions so let's just save this up the other thing that we need to bring in as I mentioned is this specific component that we have for the bottom of our table so let me just copy this go inside of our table let's actually make this on two lines and then let's copy this let's also bring in the pagination component and save this up so what we're doing is passing in a pagination component these are some options you can pass in you can look through the pagination component docs to see what options you can pass in but basically if we are passing in the page this is our page State we're passing in the on change to set that page and and the total number of pages is this math. seal that we calculated off top here now instead of passing in our users to this rows we want to use this paginated items or this sliced array so here inside of my table body instead of passing in the users I'm going to pass in the items so I'm just save this and go to our component as you you can see we have a paginated table that's currently showing four users per row now this is something you can change so you can maybe have five users per row or eight users or whatever amount of users that you want it comes with buttons to go or move uh back and forth or uh to a specific page number now another thing you can do here if you want this pagination to be outside of your table you can pass in uh the bottom component placement and you can pass in outside which is going to make this pagination to go outside of your table if you prefer that so as you can see it was pretty straightforward to render your tables dynamically with the data that we fetched inside of our server component we defined our columns and uh specifically what goes into each cell with the render cell function we created and added pagination to it now going back to the document documentation there's more you can do with uh the table component in terms of pagination or filtering and sorting for example this async pagination where you're actually loading data inside of your client component and that's a an asynchronous task so it takes time so you're actually performing or showing a loading State there in our example we fetching all of our users inside of server component and passing that to our client component and literally just paginating in uh inside our users on the client side now also you can see there is infinite pagination this is like an infinite scroll so you can get to the bottom of the table and load more it's using the use async list Hook from the react stately you can look through this if this is a specific use case for you or something you want to implement now what I want to do is to actually enhance our user table by adding this filter option so we can filter by name and also the ability to sort by name so let me just copy some code over here and I'm going to explain what I'm doing here so let's see what I've added to our user table component here the first thing I've added is this filter value state where we're going to hook this up with this input so let me just go back to our application now as you can see this is showing up that input we're going to hook this up with our own local state I'm checking to see if I do have a search filter by passing this filter value into a Boolean function or the Boolean Constructor to know whether or not I actually have a search term and then once I do have a search term all we're doing here is to get our users array and filter it based on user objects that actually contain this filter value inside of the user name and we're returning this filtered user so that's the first thing that we're doing again we're using this use memo function because we are using this filtered items to actually calculate other arrays and we want to memorize this and change it anytime that this specific values are changing now for the pagination is the same thing that we had before we have the page number we're currently on the number of rows per page we want to have the total number of pages and depending on this we are selecting or calculating and a start and end point for our array and we're just slicing this time instead of the user object we're slicing the filtered items now down here I've also included the state for our sort descriptor this is going to tell us what column we want to sort based on and what the direction for that sorting is whether ascending or descending now inside of this function we are getting our items this is the items that we got out of our pagination we are sorting through them and we're actually creating this comparison where we're actually looking up to the column on the sort descriptor so this is going to be passed to us from the table component once you click on a specific field uh if it is sortable the table component is going to invoke this function and it's going to change this state so therefore we are actually going to that column so we know which value inside of our user object we're actually comparing in this case we're just doing the name but it can be any other sortable column next thing I have added here is this on search change this is going to be invoked whenever the user is actually typing inside of this input which is just going to set this local state and bring the page back to one and if it's an empty value it's going to set the filter to an empty string on clear similarly when you start typing here is this when you're clicking on this x to clear this input is going to set the filter to unempty string and bring the page back to one now Last Thing Before actually getting to our table component is this top content so similar to where we passed in this bottom pagination or bottom content for our table you can also pass in a top content inside of our top content we rendering this input element again input is from uh next UI component and we're passing in this on search this functions we created here to this input and on clear also to this so it is actually hook hooked up with these two components the value is also set to our local state so this is now working in sync with our local state updating it and we're actually using these values to filter our users based on their name so down inside our table component we have this top content similar to the bottom content so we have put it into this top content component we created up above off and again the placement is outside the bottom content is the pagination we've added before and it is also outside of our table now the sort descriptor is the local state we created and the set sort descriptor uh is when the sort actually changes this is when the user uh clicks on it a specific sortable column uh to either select that column to be sorted or clicks again to change the direction of the Sorting now down here if you want to make a column sortable you have to pass in this allow sorting prop to your column now what I'm doing here is I'm looking to see only if I'm inside the column name I'm passing it passing allow sorting prop true so all the the other fields are not sortable for me I'm only sorting based on the name now you can also make other fields sortable by just passing this allow sorting to all of your columns I wanted it to show how you would go about just making one specific column sortable now everything else is pretty much the same if you're calling this render cell function to get the specific value or the component that we want to render in each cell now let's quick review what we have done here one more time we created some local States specifically for the filter value this is whatever the user is typing in here depending on that we filtered our users array uh depending on the users that have that specific term in their names we then ran them through the pagination so we were looking to see what page we are on and then we sliced that filter array based on the number of users that we want to show on that specific page and then we included a state full for our sorting what column we on and what direction it has and then we got our filtered value ran through this sorting to get some sorted items and we pass this sorted items down to our table instead of all the users now we also had this functions that are going to uh call this local States when the search changes or when the user actually clears the search the two components that we had for the top part including this input and the bottom component which was this pagination and that's a wrap for this video folks we implemented a dynamic table in nextjs using the next UI Library if you have any questions hit me up in the comments other than that I'll see you in the next one bye-bye
Info
Channel: Hamed Bahram
Views: 6,815
Rating: undefined out of 5
Keywords:
Id: yr-TSlSOFP8
Channel Id: undefined
Length: 28min 42sec (1722 seconds)
Published: Sat Oct 14 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.