Accepting Form Data
In this lesson, we'll take a look at how we can create a register form and accept data from that form within our route handler.
- Author
- Tom Gobich
- Published
- Apr 05
- Duration
- 12m 15s
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
Accepting Form Data
-
(upbeat music)
-
Okay, so before we actually start digging
-
into authentication,
-
we're gonna need to know how forms work.
-
So let's start by creating a signup form
-
and then we'll take it from there.
-
So first we're gonna need a controller.
-
So let's do node is make controller.
-
As your application gets older and becomes more mature,
-
the authentication flow can get rather complex.
-
So we're gonna create one controller per action
-
bound to authentication.
-
So we're gonna do a register controller,
-
login controller and a logout controller
-
for that complete flow.
-
For right now though,
-
we'll just start with our register controller
-
and let's put all of these controllers
-
specifically for authentication
-
inside of a folder called auth.
-
So if we just do auth slash and then the controller name,
-
the make controller command will create a folder called auth
-
and then the actual controller file
-
for whatever we provide on the right hand side of the slash.
-
So we could do register.
-
We wanna keep register singular.
-
So we do hyphen S there to tell the make controller command
-
that we intend for register to be singular.
-
Okay, so let's run that.
-
Cool, so now we have our new register controller
-
inside of our auth folder,
-
inside of our controllers and app directory.
-
So let's dive into that.
-
Let's do auth register controller and there it is.
-
Let's get our HTTP context uncommented.
-
We'll do async and let's do show
-
because this will be in charge of showing the register form.
-
View HTTP context, return, view, render pages.
-
We'll put this inside of an auth folder,
-
just the same as our controllers
-
and we'll call the file register.
-
All right, let's go create that view real quick.
-
So views, pages, right click that,
-
new file, create a folder called auth
-
and then inside of the auth folder,
-
create a file called register.edge.
-
We'll have our layout, go ahead and end that as well.
-
Let's go ahead and take our movie card
-
and just kind of generalize it.
-
So let's copy everything that we have inside of here,
-
right click our components, new file
-
and we'll create a file called card.edge there.
-
Paste those contents in
-
and now we just wanna get rid of everything content based.
-
We'll keep the padding for div
-
and then for the picture here, we can make that optional.
-
So let's do @if slots.picture and if,
-
go ahead and cut that out, await slots.picture
-
and render that out as an optional slot
-
and then for the actual contents,
-
we'll do await slots.main
-
so that we can put whatever we want inside of the card.
-
Okay, give that a save.
-
We should be able to jump into our movie card component now
-
and get rid of a good portion of the boilerplate here.
-
So we can go ahead and get rid of the class
-
and instead of our div, we can do @ard.
-
We're gonna want to spread in our props
-
except for the movie and we'll just let that cascade through
-
and get rid of our div there.
-
Then we'll wanna do @slot.picture
-
around our actual picture and in that slot, okay.
-
And then we can get rid of the padding for
-
and everything else just becomes our card content.
-
Get rid of these two divs and our card component
-
and lastly fix our indenting.
-
There we go, give that a save.
-
Let's make sure that worked okay.
-
Npm run div, jump into our browser and cool.
-
Our cards still all look the exact same, so we're A-okay.
-
There, jump back into our text editor
-
and let's go back to our register page.
-
Okay, so let's apply that card.
-
We'll add a class to it and we'll just do max width,
-
probably MD, I think, just so that it doesn't attempt
-
to take up the entire page and end that card.
-
So we're gonna need a form and let's go take a look
-
at our user model here and remind ourselves
-
what all we're dealing with.
-
So we have a full name, avatar URL we won't worry about
-
during registration, email and password.
-
Okay, jump back into our register page.
-
So we'll do a label, class flex, flex call
-
and we'll do a span class text, extra small,
-
font bold and call that full name.
-
And then we'll wanna do an input where the type is text
-
and the name is the same as the model's column name.
-
So that would be full name there.
-
The reason why we specifically wanna name it that
-
is because whenever we submit our form,
-
this is the name we'll be able to access it by
-
on our server side and naming it the same name
-
that we have inside of our column just simplifies
-
actually creating our user record.
-
Okay, let's give that a copy and a paste two times
-
because we're also going to need our email and a password.
-
So the type here will be email and the name
-
as we have it defined on our column is email.
-
So we'll have that as email there as well.
-
And then this one is password with a type password.
-
All right, then we need a submission button
-
so that we can actually submit our form.
-
So at button type submit at end
-
and we'll just put the text as register.
-
Let's also give our labels a little bit of spacing
-
in between one another.
-
So we'll do class Lex, Lex call gap of four.
-
Then in order to actually see this page,
-
we need to register it up to a route.
-
So let's do command P to open up our file search
-
and type in routes and hit enter there
-
to jump into our routes file.
-
Okay, and then down here, let's do router dot
-
and let's define a route group.
-
We'll provide a callback function into this
-
and any routes that we define inside
-
of this actual groups callback method
-
will get applied to anything
-
that we specify specifically for the group.
-
So for example, we can prefix our group with slash auth
-
and now any routes that we define inside of this callback
-
will actually start with slash auth.
-
Do the same thing with a name as well.
-
So we can do as auth there.
-
Okay, so let's do router dot get slash register.
-
We'll have our register controller,
-
hit tab to auto import that and we have our show method.
-
We'll name this as register show.
-
All right, so if we scroll down a little bit here,
-
hit save so that that formats.
-
What we've just done is defined a route
-
at slash auth slash register
-
and the name is now auth dot register dot show.
-
Thanks to this group, we'll be able to apply these
-
to all of the routes, simplifying the internal definition
-
for all of our authentication paths.
-
So with that defined,
-
we should be able to jump into our browser,
-
head into URL bar and go to auth slash register,
-
hit enter and there we go.
-
We see our card, our inputs are there,
-
they just don't have any styling, but they are there
-
and then we have our register button.
-
Let's get our inputs where we can see them
-
and show up a little bit of that styling.
-
So let's jump back to our register edge page.
-
On our form, we'll do a margin top of four.
-
Outside of our card, we'll do a div class flex justify
-
center so that it's centered within the page.
-
Go ahead and collapse our form down
-
and end our div after our card ends
-
and give everything there an indent.
-
Lastly, on our inputs, I think maybe we just do this
-
inside of the actual CSS file.
-
So we'll jump inside of our app dot CSS,
-
input not type equals radio and not type equals checkbox.
-
So if we have an input that's not a radio or a checkbox,
-
we'll go ahead and just apply, order, order,
-
slate 300, rounded, EX3, PY 1.5,
-
and then if it's focused, we'll do border.
-
Oh, we haven't picked a brand color yet.
-
Let's do, I guess indigo, maybe 500
-
and we'll add a small duration, 300,
-
so that it fades from our slate to our indigo.
-
Okay, give that a save.
-
If we jump back into our browser now,
-
all right, that's a little bit better.
-
At least we can see our inputs now.
-
I put the margin top on our form instead of the card.
-
So that's why the card's still flush up
-
against the border there.
-
So we'll move that margin top up to our card.
-
There we go, okay.
-
So now we need an actual handler for this form
-
whenever we click on register.
-
Right now, it's just gonna submit us back
-
to /auth register with the fields applied
-
as a query string.
-
Since we haven't specified anything specifically
-
for the form to do, so let's jump back into here.
-
We're gonna need an action for our form
-
and we'll also wanna specify the method as post.
-
Okay, let's jump back into our routes
-
and let's define it on the route.
-
So we'll do router.post this time
-
because we wanna handle the post submission
-
for our form, /register, register, controller,
-
and we'll call this store, as register store.
-
Give that a save.
-
Now we wanna jump into our register controller,
-
async, store.
-
We're gonna want our request and response
-
so that we can handle the request
-
and send an applicable response, HTTP context.
-
So when we submit our form,
-
we're gonna want to create a user
-
with the details that are provided.
-
And then once we create the user,
-
we're gonna want to log them in.
-
And then once we log them in,
-
we wanna send them off back to our application.
-
So at the end of the day,
-
our end task is to send them back to the homepage.
-
So we'll start with the ending task.
-
So let's return response
-
and we'll want to redirect them
-
to the route we've named home.
-
Then we need to grab the fields
-
that we need off of the request.
-
There's actually a few different ways that we can do it.
-
So we can do const data equals request.all.
-
And as they're telling us here within the hint,
-
this will return a reference to all our request data
-
within the body and the query string.
-
So whenever we call this,
-
we can console.log out our data
-
to see exactly what we've received.
-
Let's give that a save,
-
jump back into our register page.
-
And now the action for our form,
-
we want to send out to our new route
-
of off.register.store.
-
All right, so let's give that a save.
-
Let's jump back into our browser and give it a run.
-
So full name here,
-
we'll put John Doe, [email protected]
-
and something for the password.
-
We'll hit enter to submit that.
-
And we got returned right back to where we were
-
because we forgot about CSRF.
-
So let's jump back into our text editor
-
and on our form,
-
we want to apply the CSRF field
-
so that we get a hidden input with a CSRF token
-
that will actually allow for our registration form to submit.
-
Okay, with that in place,
-
let's jump back into our browser.
-
John Doe once more,
-
[email protected] and password.
-
Hit enter there.
-
Okay, now we are back at the homepage.
-
So if we jump back into our terminal,
-
we're going to see that we got back for our data,
-
an object with that CSRF token
-
that allowed us to submit our form,
-
our full name, email address, and the supplied password.
-
Well, we don't care about that CSRF token,
-
so all may not be applicable to us.
-
Within our text editor,
-
if we jump back to our register controller,
-
we could extract out just the fields that we care about.
-
So full name, email, and password like so,
-
or if we go back,
-
we could use request.only
-
to specify the fields that we care about.
-
And the field names that we'd supply within this array
-
are the only fields that we'll get back inside of our data.
-
So for this, we could supply full name,
-
email, and our password.
-
And with that in place,
-
if we jump back into our browser,
-
we need to add a link to this,
-
but we'll do off register there.
-
Let's do John Doe again,
-
[email protected] and another password.
-
Hit enter there.
-
Let's take another look at our terminal.
-
And there we can see that now we only have
-
our data of full name, email, and password.
-
That CSRF token was omitted
-
because we didn't specify it inside of the only array.
-
Ideally though, we would be verifying
-
that the user is actually submitting the fields
-
that we require with the actual data
-
that we require those fields to contain.
-
So we would be verifying that they're supplying
-
a full name, email, and password
-
because those are all required
-
to actually register within our application.
-
And then we would also be verifying
-
that the full name is a string,
-
the email is a valid email address,
-
and the password is probably at least eight characters long
-
or anything else that we wanna require
-
for our password fields.
-
That's where validation comes into play
-
and AdonisJS uses their own homegrown validation library
-
called vine.js to do so.
-
We'll take a look at that in the next lesson,
-
but before we move on,
-
let's add a link to our register page
-
so that we can easily get to it.
-
So we wanna jump down into our layout
-
or maybe our navigation actually.
-
So we'll jump down to our partials, our nav
-
and let's class flex justify between items center.
-
We'll wrap these three anchors in another div,
-
paste them back in,
-
and then we'll do another div
-
so that we have a left and a right side of our navigation
-
with an A, href pointing to our route,
-
auth, register, show page,
-
and we'll call that register.
-
Give that a save.
-
And now if we jump back into our browser,
-
we have our home, directors, writers,
-
as well as now a register page button.
-
Cool.
-
Let's add a quick register heading onto this as well.
-
So we'll jump back into our text editor
-
over to our register.edge page.
-
We'll put this above our form.
-
Let's do an H1, register, just like so.
-
And let's actually move that outside of the card.
-
Okay, there we go.
-
And let's see how that looks.
-
(laughs)
-
Switch that to flex call,
-
switch that to item center.
-
There we go.
-
Okay, that's the least doable.
-
Okay, let's go ahead and stop there.
-
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
-
Logging Out An Authenticated User2m 24s
-
Logging In An Existing User6m 54s
-
Remembering A User's Authenticated Session6m 55s
-
Protecting Routes with Auth, Guest, and Admin Middleware5m 36s
-
-
Filtering and Paginating Queries
-
Creating A Movie List Page3m 43s
-
Filtering A Query By Pattern Likeness7m 9s
-
Filtering Our List by Movie Status5m 47s
-
How To Apply A Dynamic Sort Filter To Your Query7m 12s
-
Joining SQL Tables To Order By A Related Column4m 49s
-
Validating Query String Filter Values7m 23s
-
How To Paginate Filtered Query Results9m 15s
-
Pagination First, Last, Next, and Previous Buttons4m 2s
-
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!