- Read Tutorial
- Watch Guide Video
So right now, we have eCommerce, Scheduling, and Enterprise. You could very well have different filters, I've left it up to you on how you want to create those. But what we need to be able to do is to have a process of resetting our values because if you look at this, just to kinda revisit our bug, you can click on eCommerce, that works, it filtered it down to eCommerce products, or portfolio items.
But now if you click on Scheduling, everything goes away.
And the reason for that makes sense, we started with a list of portfolio items, we narrowed it down to the ones that were only eCommerce and then from there, we said, hey, can you also now give me the scheduling items? Well, there aren't any because we already narrowed it down to eCommerce. We also don't have the ability to reset to view all the portfolio items, you don't really wanna ask people visiting your site to hit Refresh, that'd be a bad user experience.
So there's gonna be a couple ways that we're gonna fix this. First, we're gonna redo our filters so that they actually are standing by themselves and so that way, they don't fit in this grid, that's a UI element because I wanna add a fourth one here that's going to say all or clear filters or something like that, so that's gonna be on the UI side.
The other end of it is a little bit more tricky and so we're gonna walk through how we can do that. We're going to refit our getPortfolioItem function so that it becomes more dynamic where it can actually accept optional arguments. So we can say that we want you to go hit the API, grab our portfolio items and I want you, in some cases, to filter them and in other cases, I just want you to bring all of them. So those are gonna be our two approaches for doing that.
So let's start by opening up Visual Studio Code and let's start on the UI side, just so we know that what we are looking at is going to work. I'm going to come down to the return statement, and this is once again in our portfolio-container component. So that is in component's directory, portfolio, portfolio-container.js.
And right now we have all of our buttons here inside of the portfolio-items-wrapper and if you only have three items, that works fine, but if you have more, then you need to create the ability to have its own layout and you also could if you would like to spend a little bit more time, you could wrap this into its own component, you could create a filter component and then you'd pass props such as this.handleFilter process and that kind of thing. I'm not gonna do that in this guide but if you want some extra credit, definitely feel free to do that.
So the first thing I'm gonna do is I'm gonna create a wrapper div here and I'm gonna call this a div with the name of homepage-wrapper
. And then make sure you wrap up all of the content so go down to the very bottom and wrap everything inside of this homepage-wrapper.
Now with that in place, I'm going to create another wrapper div here and this one is going to be filter-links and this is where we're gonna place all of those buttons. So let's grab each one of those buttons and cut them out and put them inside of filter-links, hit save, and if you have pretty-error, everything will be nice and formatted.
portfolio-container.js
<div className="homepage-wrapper"> <div className="filter-links"> <button className="btn" onClick={() => this.handleFilter("eCommerce")} >
That is pretty much everything that we have to do for changing the structure.
Now let's come and let's add one more button here. So this button is going to give us the ability to clear all the filters and start fresh. So for this one, we're not gonna change the className but the handleFilter I'm going to give a constant call here where I'm gonna say CLEAR_FILTERS and then for the text, I'm just gonna say All. You can put whatever you want there but that's what I'm gonna put.
<button className="btn" onClick={() => this.handleFilter("CLEAR_FILTERS")} > All </button>
Hit Save and let's just take a look and see what we have here.
So okay, that's not horrible, this isn't ideal yet but it's not horrible. Let's go and add in all of our actual new CSS code. So I'm gonna create a new file or I should check the main style file and see if we have anything dedicated to home and it looks like we do not so let's create a new file here just for our homepage which is the only place where this style is gonna go.
So I'm gonna call this home.scss and let's create this style file. And this is where we're going to add each one of those styles starting with the homepage-wrapper, you can hit save in main and in the homepage-wrapper, since it's just a wrapper div, I'm gonna say display: grid and then grid-template-columns, it's gonna be 1fr.
So what that's going to do is make sure that we have these filter items stacked on top of the portfolio items and they go from side to side. Now you may say why did you have to do that? Because that's kind of what we already have and the reason why is I really do not like having potential styles just kinda hanging out in the ether, I don't like having the idea of not having a way of wrapping up in a single div in className that wraps up each one of these components.
When you get into things like responsive design such as customizing this look and feel for mobile, you'll discover you'll wanna make sure that you have every part of your application covered with some type of selector, some way of being able to select the style and then change it, so that's why I'm creating this homepage-wrapper div.
Now we can go and call our filter-links inside of this and for this I'm gonna use display: flex and justify-content is going to be in the center. And then let's select the buttons inside of here and I'm just gonna give them a width of 100% so that they take up all of the space. And you know what? Actually one thing, let's test this out but I don't think this is gonna work.
Okay, you know what? Actually it is. So this is working, I have experimented with a few options so justify-content here, I also worked with, playing around with space-between and then space-around, if you hit Save, you'll see it's still kind of the similar look and feel.
So this gives us now what we're looking for in regards to the user experience and the user interface. If you click on this, we still have the same bug but at least it's working from a UI perspective.
So now with all of that in place, let's go and let's work on the functionality. I'm gonna come up into our handleFilter function here, this is gonna be the very first spot where we're going to work on this and I'm gonna add a conditional. So I'm gonna say if the filter is triple equals to CLEAR_FILTERS, then I want you to simply call this.getPortfolioItems.
So that's going to call the API and it's gonna say I want you to bring all of the portfolio items back. So that's gonna be our All button and if that is not the case, so in other words, if there is a different filter, then I want you to follow the same process. So let's test this part out, see if it's working. So if I click on Scheduling, click All, it's sending us all of them back, that is working nicely.
Okay so that's the first part but we're still not done because we still have the situation where if I click on say Scheduling, and then click on Enterprise, all of our portfolio items disappear for the reasons we've already discussed. So what I'd like to do is add some new complexity into our getPortfolioItems function here. I'd like to add some dynamic behavior so that it can be extended to not just get all of the portfolio items 'cause that's all it's doing right now, it just brings all of them down, stores them all in state.
What I'd like to do is to make it so that this setState process here is more flexible. So what I'm gonna do is I'm gonna add an optional argument here where I can say filter equals null and in JavaScript, what this allows us to do is it makes it possible for us to not have to call and change 'cause say that I just added an argument here for filter.
What would have to happen is now I'd have to find every spot in this component that calls getPortfolioItems and I'd have to pass in a filter and for some of them, they don't even have a filter so there's no reason to do that but if I say filter equals null, then this is saying that filter is optional. You don't have to pass one in but if you do, the function can actually work with it.
So now that we have that, what I can do is say if filter, so if a filter was given, then I can have some behavior which is that I will update state only with the filter, and if not, I wanna bring all of them in. So let me take our original statement of just taking all of the items from the API and passing them into state, that's gonna be now in the else block.
And now I'm going to move this, I'm gonna duplicate it but then we're going to extend it and the functionality that we have right here with this.setState and this filtering process, what we can do is actually cut all of this out and then inside of this first filter block, I'll hit save just so that it's nice and formatted, inside of here, I'll paste in that filter process.
So now what we're doing is we're actually iterating over the response data, we're not iterating over state now and we're saying go through each one of these portfolio items. If the item category is equal to the filter, then I only want you to return those items.
And so now what we can do is we can streamline our handleFilter function, get rid of all of this setState code, and now make sure you add an else block or else you'll get an error, and so now what we can do is say getPortfolioItems and then just pass in the filter. Let's hit save and see if this is working.
Okay, so by default, we get all of our items, you click on eCommerce, we got out eCommerce items, click on Scheduling, we got our Scheduling items, Enterprise, it's all working perfectly. So this is really nice, I like the way that this is working, our bug is fixed.
Now if a user goes to your portfolio, they'll be able to get the expected behavior where if you click on a filter, it will actually go through and bring in all of the items in that category, it won't keep on having kind of like, this almost like Russian Nesting Doll Syndrome where you have one set of items, then you shrink it, and then all you have access to is that smaller set, that smaller collection.
Now if you click on eCommerce, the expected behaviors you'd get all of the eCommerce portfolio items. The same thing for each one of these, so that bug is fixed, we are ready to go. And in the next couple guides, we're just gonna do a few final cleanup items and then we are gonna be ready to deploy this to the web.