Use Slots To Make A Button Component
In this lesson, we'll learn about EdgeJS component slots by making a versatile button component that can gracefully handle both links and button types.
- Author
- Tom Gobich
- Published
- Feb 13
- Duration
- 6m 56s
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
Use Slots To Make A Button Component
-
(upbeat music)
-
So now if you recall back to the last lesson,
-
whenever we were inspecting the state of our component,
-
we saw that dollar sign slots object on there,
-
and it already had a couple of properties.
-
Let's go ahead and take a look at that once more.
-
So if we add our inspect back in, give this a save,
-
dive back into our browser,
-
and let's scroll all the way down
-
because that's where it was.
-
There we go.
-
Each one of the three movie card components
-
that we're using has this slots object on it.
-
Each look the exact same so far.
-
We have a context, which is an empty object,
-
and we have a main that's showing as a function.
-
If we scroll right a little bit here,
-
we'll see that's where it ends.
-
It's just a function.
-
Let's hide our browser back away now,
-
and let's get rid of our inspect once more.
-
Okay, let's dive back to our homepage,
-
and we've ignored it up till now,
-
but we are providing an exclamation point
-
before we're providing the actual name
-
of the component that we wanna use.
-
This was also there whenever we weren't using
-
the tag directly as well.
-
So whenever we were doing component,
-
we had the exclamation point there as well.
-
This exclamation point's actually specifying
-
that the component is self-closing,
-
meaning that it doesn't need an end tag.
-
So let's go back to just our tag usage here and remove this.
-
Let's give it a save, and we'll see exactly what we get.
-
So let's open our browser back up,
-
and sure enough, we get unclosed tag,
-
and it's specifically saying it's each,
-
but that's just because our movie tag
-
is eating the end here.
-
So Edge is reading this as movie card,
-
and then it's using this end down here for our movie card
-
rather than the each, which width it's supposed to be used.
-
So we need to dive back into our text editor,
-
and if we're not going to provide a self-closing indicator,
-
which is that exclamation point,
-
we need to end our component.
-
So we can save this, dive back into our browser,
-
give it a refresh, and everything works A-okay once more.
-
Cool, so let's hide that again.
-
And everything in between the start tag and the end tag
-
is our main slot that we saw whenever we inspected
-
our component state.
-
We saw that dollar sign slots,
-
and we saw that it had a main property inside of there
-
that was a function.
-
Now, we don't have any direct information
-
that we need to provide in as a slot to this card.
-
So let's go ahead and leave this as it was,
-
and instead, let's create a separate component.
-
So let's give this a save,
-
and let's dive into our card and copy our button
-
and split that into its own component.
-
So within our components directory,
-
let's right-click it, new file, and we'll do button,
-
and let's call this one index.edge.
-
So now within our components,
-
we have a button folder with an index.edge inside of it.
-
We'll go ahead and paste the button
-
that we had copied directly into here.
-
And where we have view movie would be a great spot
-
to have slot content,
-
because if we place a slot placeholder right here,
-
it allows us outside of this particular component
-
to specify any content that we want.
-
We can provide a slot placeholder
-
by doing three curly braces
-
so that we can apply raw HTML within here.
-
We'll want to await because slots are asynchronous,
-
call dollar sign slots,
-
and then we'll actually want to call the main function
-
that we saw whenever we inspected the state of our component.
-
Now, instead of building out a route for a movie show,
-
let's allow just a dynamic prop for an href within here.
-
We can give this a save, jump back into our homepage,
-
and if you remember back,
-
if we take a look at our routes here,
-
we had created these two routes
-
for flushing our Redis database
-
and clearing out a particular slug from our Redis database.
-
Let's add these buttons for those two particular endpoints.
-
So let's go back into our homepage,
-
and outside of everything else in our HTML,
-
let's do an extra div, class, we'll say fixed,
-
bottom zero, right, maybe three.
-
Let's also make these flex
-
and apply a gap of three within there as well.
-
Okay, so let's add one button.
-
So we can do @button.
-
Now, since the name of our button file is index.edge,
-
we actually don't need to specify index here.
-
We could, but we don't need to.
-
We could just leave it a button
-
and the index will be implied.
-
The same as if you were working
-
with just traditional HTML directory files.
-
Okay, so for our props, we'll specify our href.
-
For right now, we'll just do a pound,
-
and then we'll have our end button.
-
Anything in between the start and end tag for our component
-
is our main slot,
-
meaning that we can directly apply
-
whatever content we want to our button
-
right here for our main slot.
-
So let's add the text flush-redis-db here.
-
Let's go and give this a save
-
and jump back into our browser and see what it looks like.
-
So down in the bottom right-hand corner,
-
we have our flush-redis-db button.
-
Currently it doesn't do anything,
-
but we can see that our slot content
-
is being directly applied to the button itself
-
as the content.
-
Now, it would be really nice if the bottom left
-
and bottom right-hand corners were not rounded.
-
So let's dive back into our component there
-
and let's take care of that.
-
So let's dive back into our index button.
-
Let's move our class out into a variable.
-
So we'll cut all of this
-
and we'll do @let className equals
-
and paste it in a string.
-
And let's make use of our props HTML.
-
So we'll do two curly braces.
-
So $props to @ttrs,
-
and then we're going to want to merge,
-
provide an object, a class, array of our class name.
-
Now this props to @ttrs will actually apply
-
our href automatically for us.
-
So we can actually get rid of that altogether as well.
-
One last thing,
-
sometimes we want a button to just be a type of a button.
-
So we can also wrap this in an if.
-
So if props.has href,
-
then we'll want to use an anchor.
-
Otherwise, let's give this an indent.
-
We'll do an actual button
-
and then we'll do our props.merge class,
-
className into @ttrs, just like so.
-
And then our three curly braces,
-
but wait, slots.main.
-
Lastly, let's end our if, just like so.
-
Okay, cool.
-
So now if we provide an href into this component,
-
it'll be rendered out as an anchor tag.
-
Otherwise, it'll be rendered out as a button.
-
You will notice that the HTML tag
-
is the only thing that's changed with these two.
-
So if you really wanted to,
-
you could inject the tag itself as well.
-
So we could switch this variable here to a ternary
-
@let nodeName equals.
-
If the props.has an href value,
-
we'll want to use an anchor.
-
Otherwise, we'll use a button.
-
And now we can get rid of our if
-
and get rid of our else,
-
take this back down,
-
and we can use double curly braces
-
to just directly render in the node name for the element.
-
So nodeName, just like so.
-
NodeName, give that a save.
-
If we dive back into our browser,
-
our button down here still looks a-okay.
-
Give it a right click and let's inspect it.
-
And look at that, it's an anchor.
-
If we bring our text editor back up,
-
go back into our homepage,
-
and let's go ahead and just get rid of the href.
-
Give that a save.
-
Let's take a look at our fixed element.
-
And look at that, now it's a button.
-
So that seems to be working a-okay as well.
-
Got a little sidetracked.
-
We were trying to take care of the border radius
-
there on the bottom.
-
So let's do that real quick as well.
-
Let's put our href back in.
-
Now we can specify a class on the outside of here.
-
We'll do rounded, bottom, none.
-
And that should remove the border radius from the bottom.
-
And sure enough, it did.
-
Awesome. That's looking great.
-
So now we have a button component that we can use anywhere.
-
And that allows us to simplify our cards
-
by not redefining the HTML for that button.
-
So let's go ahead and hide our browser back away.
-
Let's dive into our movie card component.
-
And now we can get rid of this button
-
and instead use our button component.
-
Provide the href.
-
Go ahead and just copy this here.
-
Cut that out.
-
Paste it right into there.
-
All of our styling should be the same.
-
I don't think we did anything special with that.
-
So we can get rid of the element
-
and replace the end with our button end.
-
If we give this a save,
-
we can dive back into our browser.
-
And look at that.
-
Everything looks the exact same as before.
-
We can click them and dive right into our pages
-
for our movies.
-
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
-
The Flow of Middleware7m 49s
-
Authenticating A Newly Registered User4m 14s
-
Checking 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
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!