Filtering By User's Watched Status
In this lesson, we'll learn how to add a filter to our user's watchlist allowing them to show only movies they have or have not watched.
- Author
- Tom Gobich
- Published
- May 16
- Duration
- 6m 7s
![Tom Gobich](/img/1/profile/avatar_1703713552864.jpg)
Developer, dog lover, and burrito eater. Currently teaching AdonisJS, a fully featured NodeJS framework, and running Adocasts where I post new lessons weekly. Professionally, I work with JavaScript, .Net C#, and SQL Server.
Adocasts
Burlington, KY
Transcript
Filtering By User's Watched Status
-
(upbeat music)
-
Next for our watch list,
-
let's give our users the ability to filter
-
by all their watch list movies,
-
just their watch list movies that they have watched
-
and those that they have not watched.
-
So let's hide our browser away,
-
head into our watch list page,
-
scroll on up to where we have our filters
-
and let's put this in between our status and our sort.
-
Paste that right in there, it'll be another select.
-
The label for this, maybe we'll do something like watched
-
and then for the name, we'll just do watched as well.
-
We'll leave our all option in
-
and we'll go ahead and just put some manual options
-
in here as well.
-
So option, value, and we'll do watched
-
with a label of watched
-
and we'll do an option value of unwatched
-
with a label of not watched.
-
Give that a save.
-
And now we need to account for this new property
-
within a validator.
-
So we'll scroll up to our movie validators.
-
We're gonna wanna leave our movie filter validator as is,
-
but we can reuse the schema that's inside of here.
-
So if we cut out our whole object here
-
and instead put it inside of a variable
-
say like shared movie filter schema equals
-
and then paste it in, give that a save
-
to fix whatever formatting issues we have
-
and then take the shared movie filter schema,
-
scroll down to our movie filter validator.
-
We can now paste that in, making our vine compile
-
for our movie filter validator happy.
-
And it also allows us to define an additional validator
-
to make use of those same schema properties.
-
So we can do watch list filter validator
-
equals vine.compile, define a new schema,
-
define a new vine.object
-
and then we can spread in
-
our shared movie filter schema properties
-
by doing dot get properties and calling that.
-
And that will spread in to this particular object,
-
all of the properties that we have defined
-
within our shared movie filter schema vine object here.
-
So we've already applied our search status
-
and sort within our watch list filter validator,
-
leaving us with just needing to define our watched filter.
-
And we can say, this is vine dot and you know what?
-
Let's use enum because we have
-
some very specific properties here.
-
And we can say that it should only be,
-
let's rename all to just all rather than an empty string,
-
watched or unwatched.
-
So now we're gonna ensure that it's one of those three.
-
Give it a save.
-
Let's quickly jump back into our watch list page
-
and give all a literal name of all there.
-
And let's scroll back up
-
and jump into our watch list controller next.
-
Scroll up to the top where we have our filters.
-
And first we're going to wanna swap out our validator.
-
So now we'll use our watch list filter validator
-
and import that,
-
which will leave us with an unused movie filter validator
-
import that we can now get rid of.
-
And let's go ahead and pluck out of our filters,
-
our watched filter,
-
and then we can spread the rest as the filters variable,
-
which will leave our get filtered method
-
to apply the filters that we have shared.
-
And we can just apply the watched filter
-
specifically in this one use case
-
that we're actually going to use it.
-
So we're gonna want to break our where has down for this.
-
So I'm gonna move that into a new line
-
and break that down a little bit more.
-
And we're gonna want to apply our watched filter
-
specifically on the watch list where has.
-
So if our watched filter equals watched,
-
then we're gonna want to take our query.
-
And since we're already using query,
-
we need to call this something else.
-
So we'll call this our watch list.
-
So watch list dot.
-
And since we're filtering to those that have been watched,
-
but want to do a where not null watched at.
-
So we wanna get our movies where it has a watch list
-
specifically where the watched at is not null,
-
meaning that the movie has been watched.
-
Otherwise, if watched equals unwatched,
-
then we'll wanna take our watch list query
-
and we'll wanna apply a where null check for watched at.
-
So if the filter is for watched,
-
then we'll limit our movies to where the watch list
-
has a watched at value.
-
Otherwise, if we're filtering by the unwatched movies,
-
then we wanna get where the watched at is specifically null,
-
meaning that it doesn't have a value
-
and hence has not been watched.
-
If it's all, then we don't wanna do either of these
-
and we can just leave the where has as is.
-
So let's give that a save,
-
jump back into our browser and let's give it a test.
-
So let's switch our watched filter
-
to just those that have been watched.
-
Give it a search.
-
All right, we have three here.
-
All of our buttons are marked as unwatched.
-
So that seems to be working.
-
Let's switch it to not watched.
-
We also need to populate in the default value there,
-
but switch it to not watched here.
-
And now all of these are marked as watched.
-
If we marked one of these as watched,
-
it's now gone whenever we get back our filtered results.
-
Awesome.
-
So let's go populate in our watch default value real quick.
-
Jump back into our watchlist page
-
and we'll do HTML, ATT, RS here.
-
Apply selected when our filters dot,
-
oh, you know what?
-
We plucked it out of filters.
-
Let's go back into our watchlist controller.
-
Right here, we're splitting them apart
-
from our filtered and our watched.
-
Let's go ahead and just leave those together after all.
-
Switch this to filters.watched
-
and our get filtered call can just ignore it.
-
All right, let's scroll back down to our watchlist page
-
and we'll do filtered dot watched equals all.
-
Then we'll have that selected.
-
Give this section here a copy
-
and paste it in for these two here as well.
-
And just switch this to watched and unwatched.
-
I'm gonna break these down here
-
to clean it up a little bit.
-
And there we go.
-
One more thing real quick is we'll jump into our movies
-
and we'll make this enum here optional
-
because all will be the default.
-
Awesome.
-
So with that in play,
-
let's go ahead and test everything out once more.
-
So we'll switch this to all, search.
-
There we go.
-
We get back all.
-
Switch this to watched.
-
And there we go.
-
We get back just our watched.
-
I'm gonna move one of these to unwatched.
-
Let's move cabaret back to unwatched.
-
And, oh, look at that.
-
It got rid of our query string.
-
So let's fix that real quick too.
-
Jump back into our watchlist controller
-
where we have our toggle.
-
I'll let's say this specifically the watch toggle
-
and we'll redirect back with the same query strings
-
that we already have applied.
-
So we'll keep the query strings
-
using the with query string method.
-
Jump back into our browser here.
-
All right, let's reapply a query.
-
So we'll go back to, how's about not watched?
-
Jump back into here,
-
switch cabaret back to being watched.
-
And there we go.
-
So now we got redirected back
-
and we kept our query string,
-
meaning that we kept all of our nice filters here.
-
Switch back to watched, search,
-
get rid of cabaret, mark that as unwatched.
-
There we go.
-
And we keep all of our filters still.
-
So awesome.
-
Everything seems to be working A-okay.
-
So we should have our watchlist fully implemented now.
-
Introduction
-
Fundamentals
-
2.0Routes and How To Create Them5m 24s
-
2.1Rendering a View for a Route6m 30s
-
2.2Linking Between Routes7m 52s
-
2.3Loading A Movie Using Route Parameters9m 18s
-
2.4Validating Route Parameters6m 7s
-
2.5Vite and Our Assets6m 39s
-
2.6Setting Up Tailwind CSS7m 5s
-
2.7Reading and Supporting Markdown Content4m 32s
-
2.8Listing Movies from their Markdown Files8m 51s
-
2.9Extracting Reusable Code with Services7m 4s
-
2.10Cleaning Up Routes with Controllers4m 52s
-
2.11Defining A Structure for our Movie using Models9m 38s
-
2.12Singleton Services and the Idea of Caching6m 11s
-
2.13Environment Variables and their Validation4m 16s
-
2.14Improved Caching with Redis10m 44s
-
2.15Deleting Items and Flushing our Redis Cache6m 46s
-
2.16Quick Start Apps with Custom Starter Kits6m 28s
-
2.17Easy Imports with NodeJS Subpath Imports8m 40s
-
-
Building Views with EdgeJS
-
3.0EdgeJS Templating Basics8m 49s
-
3.1HTML Attribute and Class Utilities6m 9s
-
3.2Making A Reusable Movie Card Component10m 24s
-
3.3Component Tags, State, and Props4m 53s
-
3.4Use Slots To Make A Button Component6m 56s
-
3.5Extracting A Layout Component5m 13s
-
3.6State vs Share Data Flow2m 59s
-
3.7Share vs Global Data Flow6m 8s
-
3.8Form Basics and CSRF Protection6m 13s
-
3.9HTTP Method Spoofing HTML Forms3m 3s
-
3.10Easy SVG Icons with Edge Iconify7m 57s
-
-
Database and Lucid ORM Basics
-
4.0Configuring Lucid and our Database Connection4m 3s
-
4.1Understanding our Database Schema9m 35s
-
4.2Introducing and Defining Database Migrations18m 35s
-
4.3The Flow of Migrations8m 28s
-
4.4Introducing Lucid Models5m 43s
-
4.5Defining Our Models6m 49s
-
4.6The Basics of CRUD11m 56s
-
4.7Defining Required Data with Seeders11m 11s
-
4.8Stubbing Fake Data with Model Factories13m 48s
-
4.9Querying Our Movies with the Query Builder15m 30s
-
4.10Unmapped and Computed Model Properties3m 24s
-
4.11Altering Tables with Migrations7m 6s
-
4.12Adding A Profile Model, Migration, Factory, and Controller2m 57s
-
4.13SQL Parameters and Injection Protection9m 19s
-
4.14Reusable Query Statements with Model Query Scopes8m 11s
-
4.15Tapping into Model Factory States9m 15s
-
4.16Querying Recently Released and Coming Soon Movies4m 59s
-
4.17Generating A Unique Movie Slug With Model Hooks7m 59s
-
-
Lucid ORM Relationships
-
5.0Defining One to One Relationships Within Lucid Models5m 49s
-
5.1Model Factory Relationships2m 54s
-
5.2Querying Relationships and Eager Vs Lazy Loading5m 17s
-
5.3Cascading and Deleting Model Relationships5m 16s
-
5.4Defining One to Many Relationships with Lucid Models6m 56s
-
5.5Seeding Movies with One to Many Model Factory Relationships5m 24s
-
5.6Listing A Director's Movies with Relationship Existence Queries8m 41s
-
5.7Listing and Counting a Writer's Movies8m 41s
-
5.8Using Eager and Lazy Loading to Load A Movie's Writer and Director5m 18s
-
5.9Defining Many-To-Many Relationships and Pivot Columns9m 48s
-
5.10Many-To-Many Model Factory Relationships4m 50s
-
5.11A Deep Dive Into Relationship CRUD with Models18m 5s
-
5.12How To Create Factory Relationships from a Pool of Data13m 55s
-
5.13How To Query, Sort, and Filter by Pivot Table Data9m 47s
-
-
Working With Forms
-
6.0Accepting Form Data12m 15s
-
6.1Validating Form Data with VineJS9m 29s
-
6.2Displaying Validation Errors and Validating from our Request7m 16s
-
6.3Reusing Old Form Values After A Validation Error2m 3s
-
6.4Creating An EdgeJS Form Input Component5m 28s
-
6.5Creating A Login Form and Validator5m 1s
-
6.6How To Create A Custom VineJS Validation Rule9m 7s
-
-
Authentication & Middleware
-
7.0The Flow of Middleware7m 49s
-
7.1Authenticating A Newly Registered User4m 14s
-
7.2Checking For and Populating an Authenticated User2m 10s
-
7.3Logging Out An Authenticated User2m 24s
-
7.4Logging In An Existing User6m 54s
-
7.5Remembering A User's Authenticated Session6m 55s
-
7.6Protecting Routes with Auth, Guest, and Admin Middleware5m 36s
-
-
Filtering and Paginating Queries
-
8.0Creating A Movie List Page3m 43s
-
8.1Filtering A Query By Pattern Likeness7m 9s
-
8.2Filtering Our List by Movie Status5m 47s
-
8.3How To Apply A Dynamic Sort Filter To Your Query7m 12s
-
8.4Joining SQL Tables To Order By A Related Column4m 49s
-
8.5Validating Query String Filter Values7m 24s
-
8.6How To Paginate Filtered Query Results9m 15s
-
8.7Pagination First, Last, Next, and Previous Buttons4m 3s
-
-
User Watchlist
-
9.0An Alternative Approach to Many-To-Many Relationships4m 56s
-
9.1Toggling A Movie in an Authenticated User's Watchlist9m 56s
-
9.2Listing and Filtering User Watchlist Items7m 31s
-
9.3Allowing Users To Toggle A Movie As Watched4m 44s
-
9.4Filtering By User's Watched Status6m 7s
-
9.5Defining A Composite Unique Constraint4m 47s
-
9.6Persist Filters Easily with Lucid's Query String Method3m 58s
-
-
User Profiles
-
10.0How to Create and Fix Missing User Profiles in Your Application7m 37s
-
10.1Using Dependency Injection to Update A User's Profile9m 46s
-
10.2Saving All Or Nothing with Database Transactions5m 15s
-
10.3Uploading and Displaying User Avatars15m 29s
-
10.4Displaying A User's Profile6m 1s
-
10.5Filtering, Preloading, and Sorting By Relationship7m 6s
-
-
Admin Panel
-
11.0Creating An Admin Layout7m 14s
-
11.1Counting Stats for our Admin Dashboard5m 43s
-
11.2Paginated Admin Movie Table13m 2s
-
11.3Allowing Admins to Create Movies16m 39s
-
11.4Allowing Admins to Update Movies and Clear Values13m 27s
-
11.5How To Use One Form to Create or Edit Movies5m 32s
-
Uploading Movie Cover Images in our Create or Edit Form10m 29s
-
Using A Wildcard Route Param to Download Storage Images7m 57s
-
Posting Objects, Arrays, and an Array of Objects in HTML Forms26m 26s
-
Managed Transactions and Syncing Movie Cast Members15m 55s
-
Allowing Admins to Delete Movies and their Relationships7m 42s
-
Thank You for Watching!0m 31s
-
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!