تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Testing topics prop0:00

As I mentioned at the outset of the previous episode, in an ideal world I would have a menu of all topics under this page heading here so that I'm able to quickly select a topic rather than having to find the relevant topic in the posts down here. I think that that should be pretty straightforward to accomplish, but obviously if we're going to output all the topics, again, we need to pass them down to the front end. We'll start with a test. Alright, so in the test file, we already have ItPassesPostsToTheVue, and I'm going to place this test directly underneath, just so that we group together similar test types. ItPassesTopicsToTheVue, and inside here we're going to need some topics, so let's say Topic, Factory, maybe we'll create three topics for this test.

It Passes Topics to the Vue, and inside here we're going to need some topics, so let's say Topic, Factory, maybe we'll create three topics for this test. Alright, we can get the root of Post.index, and we're not going to be asserting a paginated resource because there's no need to paginate topics. There are only going to be a limited number of them, and they're controlled by us as administrators. They're not a CRUD resource. So instead, we'll just assert that it has a resource called Topics, and that should be a topic resource collection wrapping the topics that we create up here. By the way, we don't have to worry about ordering for topics just yet. In the future, we might order them alphabetically, but for now, certainly for our initial test,

Passing topics from controller1:25

By the way, we don't have to worry about ordering for topics just yet. In the future, we might order them alphabetically, but for now, certainly for our initial test, we'll leave it as is, the order that comes directly from the database. Okay, execute the test, and of course it fails because the property topics doesn't exist. Let's go fix it. We'll jump into the PostController. Here's our index method, and post selected topic. We'll sandwich topics right in between the two. We can use a closure so that we don't load topics unnecessarily, and then all we need is a TopicResourceCollection that wraps Topic all, grabbing all of the topics from.

We can use a closure so that we don't load topics unnecessarily, and then all we need is a topic resource collection that wraps topic all, grabbing all of the topics from the database. Let's rerun the test, and yeah, you can see that it passes. So now in our index.view component, well, we can accept a new prop, Topics, which we can make use of at the top of our file. Here we have our link, which is back to all posts. I guess that should actually have a v-if, right? v-if selectedTopic, because we shouldn't show that link if we're already on all posts. Anyway, off topic, let's get back on track.

Extracting Pill component2:27

VIF selected topic, because we shouldn't show that link if we're already on all posts. Anyway, off topic, let's get back on track. Perhaps down here we could have a menu, and then we'll have a list item, and this is where we'll loop over those topics. So topic in Topics, and of course we'll want to provide a key for this, which we can use topic.id for, and then once we're inside there, well, we basically want to make use of this here, which is the pill component. I want to output it as a list, a line of pills. Rather than copying and pasting this, why don't we extract this pill to its own component? Let's copy the code, and if we come up to components, we can create a new file, pill.view.

Rather than copying and pasting this, why don't we extract this pill to its own component? Let's copy the code, and if we come up to components, we can create a new file, pill.view. We'll add our template tag, drop this in place. I want to make it very generic, so let's get rid of this and instead include a slot. I'll get rid of the href as well, although we should say, perhaps in Define Props, that you will be giving a href to the component, and then up here I can say href equals href, and the class should be absolutely fine as it is, at least for now. We'll come back to it in just a moment. Okay, so if we jump back to our post /index, I should be able to switch this out with our new pill, which can set the href to this value here, and it can set the content

Okay, so if we jump back to our post/index, I should be able to switch this out with our new Pill, which can set the href to this value here, and it can set the content to post.topic.name. Okay, let's get rid of that, and then we could more or less do the same. Let's copy and paste this, bring it to the top. Inside the menu list items, we'll drop in our Pill. That's going to be the same, but obviously we don't go through the post. We go directly through the topic. Hmm, would that work? Let's find out.

Hmm, would that work? Let's find out. All right, that worked. It looks ugly. It needs a lot of work, but it is working correctly, and as I click through these, you see the different topics that are available. Just thinking about it, why don't we get rid of this back to allPost link and just have an allPosts pill instead? That would make more sense, and it would probably fit the theme better. We can come into our component and delete that link, and then we'll have a manual list

Styling topics menu4:40

That would make more sense, and it would probably fit the theme better. We can come into our component and delete that link, and then we'll have a manual list item here at the top where we can include that Pill component, and of course, inside that Pill, we can say all posts, and the href is going to point to route, and we're looking for posts.index without anything else attached to it. So there we go. All posts, general, reviews, questions, conspiracies, fan fiction. That's so cool. Let's use Tailwind to style this so that it looks a little better than it does currently. Let's add some classes to this menu tag, and perhaps flex, okay, and we could use space

Let's use Tailwind to style this so that it looks a little better than it does currently. Let's add some classes to this menu tag, and perhaps flex, okay, and we could use space-x-1, okay, maybe mt-3 or mt-4. All right, that's already looking great. What happens if we move into a mobile view here? Yeah, that doesn't look so good. So I think what we need to do is go into the pill component, and we can say whitespace-nowrap. Ah, that's better. They now force themselves onto a single line.

Ah, that's better. They now force themselves onto a single line. Obviously we have a new problem in that they go beyond the edge of the screen, and we have this horrible white bar, but I think a horizontal scroll bar would look quite nice here and would work quite well. So overflow-x: auto, yeah, there we go. And it's cutting off the bottom border, and the scroll bar's getting in the way a little bit, so how about we use padding-bottom: 2? That resolves that nicely. And then let's also do a padding-top: 1, yeah, and to compensate we can make the margin.

Adding active pill state6:16

That resolves that nicely. And then let's also do a padding-top of 1, yeah, and to compensate we can make the margin-top of 3, okay, that looks great. It would be nice if our pill component supported some form of filled or active state. So at the moment, obviously, yeah, I can click through, but I don't know from looking at the menu which item is currently selected. So what if when you click on one of these, it stays purple with that white coloring in the middle, and that is the filled or active state of a pill? Let's open up the pill component. Obviously we define a href prop.

Let's open up the pill component. Obviously, we define a href prop. Let's switch this out with object syntax. We'll say href, we'll make that a required property, and then underneath we'll have our second property which we'll call filled. You could go with active as well, I guess, but active is already a keyword in HTML, so keep that in mind. And for this, what do we want to say? Let's set the default to false. By default, you are not filled.

Let's set the default to false. By default, you are not filled. Let's now assign the correct classes based on that filled property. I'll use object syntax for this, and I'm going to set essentially the same classes that we used for hover, but we'll remove the hover prefix from both, and I only want those to show if we are filled. Now on the front end, we can work out whether a pill should be filled based on the selectedTopic. We can say filled is equal to, is this topic.id equal to the selectedTopic, and remember it can be null, so we'll use optional chaining syntax to say selectedTopic.id.

We can say filled is equal to, is this topic.id equal to the selectedTopic, and remember it can be null, so we'll use optional training syntax to say selectedTopic.id. If those two are equal, then yes, it should be filled. Does that work? The brighter text color doesn't seem to have taken effect. I'm pretty sure this is a specificity issue between text-indigo-50 and text-pink-500, and there's a cheeky way to fix this, which is to basically prefix the class with an exclamation mark to mark it as important. Yeah, there we go. Questions, conspiracies, fanfiction, reviews, general.

Yeah, there we go. Questions, conspiracies, fanfiction, reviews, general. And for all posts, we can do something quite similar. All we have to say is it's filled if the selected topic is equal to null, if it doesn't exist. So now all posts is selected, general, reviews, questions, conspiracies, fanfiction, and I imagine we can do the same as we click through on this side as well. General, yep, general is highlighted. That works perfectly. Awesome. So this is much better than it was before, much nicer for the user.

Next: assign topic on create8:51

Awesome. So this is much better than it was before, much nicer for the user. Of course, at the moment, if you go to create a Post, you can't actually assign a topic. That's a glaring omission. Let's fix it in the next episode.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟