Allowing Users To Toggle A Movie As Watched
In this lesson, we'll learn how to allow users to toggle whether they've watched a movie or not within their watchlist.
- Author
- Tom Gobich
- Published
- May 16
- Duration
- 4m 44s
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
Allowing Users To Toggle A Movie As Watched
-
(upbeat music)
-
Next, whenever we're specifically on our watch list,
-
we're not gonna wanna show
-
that this movie is in their watch list.
-
Instead, we're gonna want to add the ability
-
to mark a movie as watched.
-
I'm gonna add that elsewhere as well,
-
but primarily it would be good to have it in here
-
since we won't have that in your watch list button.
-
So let's go ahead and get back into our text editor
-
and we're gonna wanna jump into our card component.
-
So let's scroll back down to our movie card.
-
We are still going to need movie.watchlist populated
-
in order to determine if the movie's been watched
-
for our watch list page,
-
but we're not gonna want this actual button to show.
-
So since we're only going to add in
-
the actual is a movie watch toggle on our watch list page,
-
what we can do is an if slots.action.
-
If we have an action slot,
-
then we can go ahead and render that out.
-
So slots.action, and then switch this to an else if.
-
And that will allow us to essentially take this form
-
and move it out into our watch list page
-
since this is the one and only page
-
that we're gonna want this form to be on.
-
We can then change our movie card
-
from a self-closing component to a normal one, end it.
-
And then inside of here, we can do an at slot action,
-
end the slot and paste this form in.
-
To make things a little bit easier,
-
we can also wrap the first watch list item
-
and call that watch list.
-
So we'll do at let watch list equals movie.watchlist at zero
-
to grab the item at the zero index.
-
Our ternary here for our button text
-
would then switch to watch list.watchedAt.
-
So if we have a watched at value,
-
then that means that the movie was watched.
-
So for our text, we can then say mark as unwatched
-
or something of a sort.
-
And then if the movie has not been watched,
-
then we'll say something like mark as watched.
-
And right now we don't have a route for this actual toggle.
-
So let's go create that next.
-
Before we do, let's just make sure
-
everything's rendering out okay on our page.
-
Cool, so we have marked as watched, marked as watched
-
because we don't have any marked as watched.
-
Let's jump back into our routes file.
-
We've already defined a handler for this.
-
We just haven't actually done anything with the handler.
-
So we'll do router.host watchlists,
-
movie ID and toggle watched.
-
Specify that we wanna handle this
-
with our watch list controller
-
and the toggle watched method is watchlists toggle.watched.
-
Give that a save and it'll probably break it down.
-
Yep, and let's go ahead and jump into
-
our watch list controller and handle that real quick.
-
So scroll on down to our toggle watch method.
-
We're gonna want our response, rams and auth.
-
And first thing we're gonna wanna do is grab our watch list.
-
So we'll do const watch list equals await watch list
-
dot query where, and we can scroll up here
-
and grab our user and movie ID
-
and paste that in down here, where movie ID and user ID
-
and grab just the first item.
-
Now, if we're within this method,
-
we should actually already have a watch list item.
-
So we could do first or fail here
-
so that we get a 404 error
-
if the watch list item cannot actually be found.
-
So then with that watch list,
-
we just wanna do an if watch list dot watched at.
-
So if there's a value for watched at,
-
then we just want to clear that out.
-
So watch list dot watched at now equals null.
-
Otherwise watch list dot watch at equals date time.
-
Import that from Luxon dot now.
-
Then we'll just await watch list,
-
save and return response redirects right on back.
-
Jump back into our watch list page.
-
And now instead of watch list dot toggle,
-
we wanna watch list dot toggle dot watched.
-
Params should be the same.
-
So we can leave that as is, give that a save.
-
Let's jump back into our browser and let's give it a test.
-
So let's marked as watched a movie.
-
Cool, so now our text says marked as unwatched.
-
We can click it again.
-
It's back to marked as watched.
-
Click it again, back to unwatched.
-
Awesome, do that one there as well.
-
And this one, cool.
-
So everything does seem to be working there A-okay.
-
Now, if you would like some extra homework with this,
-
go ahead and try adding in an additional filter
-
specifically for the watch list page
-
that allows you to limit to either movies that are watched
-
or unwatched for an authenticated user.
-
Before we round out this lesson though,
-
we do need to add in our middleware.
-
So if we jump back into our routes,
-
right now we don't have any middleware
-
applied to our watch lists.
-
For all three of these,
-
really we just want the user to be authenticated
-
in order to perform these actions.
-
So we could individually add the middleware
-
one by one to each of these,
-
or we could create a router dot group,
-
move these three routes into that group.
-
And we do have a variation with our prefix.
-
So we'll leave that off
-
because this one's watch list singular
-
and this one's watch list plural
-
and this one's watch list plural.
-
So we'll leave prefix off
-
and instead just do as watch lists
-
and then use middleware.off
-
to ensure we have an authenticated user
-
in order to be able to use these routes.
-
And then since we have as watch list
-
as a name prefix for the group,
-
we can remove watch lists from the name here.
-
Give it a save, jump back into our browser real quick,
-
just make sure everything works.
-
Looks good there.
-
Do our filter vest there and awesome.
-
Everything still seems to be working A-okay.
-
Introduction
-
Fundamentals
-
2.0Routes and How To Create Them5m 23s
-
2.1Rendering a View for a Route6m 29s
-
2.2Linking Between Routes7m 51s
-
2.3Loading A Movie Using Route Parameters9m 17s
-
2.4Validating Route Parameters6m 6s
-
2.5Vite and Our Assets6m 38s
-
2.6Setting Up Tailwind CSS9m 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 7s
-
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 23s
-
8.6How To Paginate Filtered Query Results9m 15s
-
8.7Pagination First, Last, Next, and Previous Buttons4m 2s
-
-
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 34s
-
9.3Allowing Users To Toggle A Movie As Watched4m 44s
-
9.4Filtering By User's Watched Status6m 7s
-
9.5Defining A Composite Unique Constraint4m 46s
-
Persist Filters Easily with Lucid's Query String Method3m 58s
-
-
User Profiles
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!