Today, we're diving into one of the
fundamental concepts in Dart development: enums. You might be wondering,
"What exactly are enums, and how can I use them to level up my development
skills?" Well, stick around because we've got you. In this video, we'll start with the basics,
explaining what enums are and how to use them. Then, we'll add some extra functionalities to
our enums, making them a little bit more usable. Lastly, we'll touch on Dart's enhanced enums, and
we'll do all of this by modifying this app screen. Starter code linked in the description
below to ensure all our constant values, from the color to the order
state, the state description, as well as the icons, are all
stored as part of a single enum. Let's get to it. I'm pretty sure many of you might have noticed
that if you wanted to store a list of constant strings, you could just do something like this:
create a class and store them like that. But stop! Let's use enums for that.
An enum, short for enumeration, is a way to define a set of constant values.
It's super handy when you have a fixed set of options or states in your app.
Let's look at some basic code. As mentioned before, the link to the starter
code can be found in the description down below. What you will find in there are some files,
and one of those files is this file right here called "enums." In here, you will find a custom
widget that takes in a couple of parameters: it takes in color, title, subtitle, icon, whether
to show the line, and whether it's active or not. This is to display the status of our order.
So, let's get to writing some enum code. To get started, you will have to declare your
enum. To do that, you type the word "enum" in small letters, followed by the name of your enum.
In this instance, it's "orderStatus" because we are dealing with the status of the order, and it
can have multiple values: processing, in transit, and delivered. Let's do that. The first value
will be "processing," and the last one will be "delivered." There you go; you have your
first enum. You can try to use it like this: you type the enum name followed by a dot
and the value that you're trying to access. But this does not return a string value; it
returns an instance of the "orderStatus." So, since our widget is expecting a string value,
we will convert this to a string, and we get something that looks like this.
This is not pretty. The `toString` method returns the actual
string representation of our enum, but we want the string representation of our enum value.
To do that, Dart provides a getter on the values; one of the getters is called "name." We use that
and save, and this is what we get. Let's make that uppercase, just for good measure. We can try
and do the same for the rest of the values, so we do that for "in transit," name, and we
save, and we see our next problem. We want this string representation to be proper, in this
format, meaning there needs to be a space between the "in" and the "transit." How do we actually
achieve that? Let's jump into our next topic. In Dart, you can actually add methods
to your enums. So, what we're going to do is add a method getter "humanReadable," and
we're going to switch on the `this` variable, meaning we are switching on the actual
"orderStatus" itself. We get this error. What this error is saying is that we need
to specify all the cases. We specify our cases for "processing," "in transit," and
"delivered," and we still now get this error, meaning this cannot be static. Now we save that,
and now we have another getter on our enums. Let's use that instead of "name": "humanReadable." And
there you go. We can do that for "in transit" as well. There you go, and we can do the
same for "delivered" as well. There you go. Now, this is great, but suppose we wanted to
associate our enum values with more values. For instance, we wanted to associate each enum
value with a color, a description, a subtitle, or an icon. Now, we would pretty much have
to do this again and again for the color, for the subtitle, for everything that we have.
So, I don't think this is going to work. Now, let's jump on to the next topic that Dart 2.17
introduced: enhanced enums, which makes enums behave more like classes. We can declare our
enums with fields, static or instance members, methods, and all of that. So, let's declare some
fields. For this one, we'll declare the fields for "title," "description," "icon," and I think we'll
do one more for the color as well. One more trick that I like doing here is converting my enum to a
class so that I can have VS Code do the heavy work of creating the constructor for me. I will make
all of these fields required and change this back to an enum. After doing this, you will see that
our enum constructor now needs to be constant, so we'll do that, and our enum values now need
to be declared with the given fields. So, let's do that for "processing." We'll give it the color
of "Colors.amber," we'll also give it the title, the description, and we'll also give it the
icon as well. We will then go ahead and do the same for the other values: "in transit" and
"delivered." We will pass the values as needed and end it with a semicolon. You see that we're
passing all the values: the color, the title, description, and the icon. Now that we have this,
we can go ahead and try to use it. Let's go ahead and do that. Instead of passing it like this,
we can simply call the title for the titles, and we'll pass the description as the subtitle.
We'll do the same thing for the icon by saying "orderStatus.processing.icon," and we
will do the same thing for the color: "orderStatus.processing.color." Then, I will
restart just to show you that it's maintaining the state, and I will change the color, save, and
you will see that it's actually very responsive. Now that we have that, I think we will do the
same thing for the other statuses as well. We'll copy the first one, duplicate it around, change
that to "in transit," copy that, change that to "delivered," and also change the "show line"
to false. And we are back where we started, but as you can see, we are kind of repeating the
same code again and again. There should be an easier way to do this. In a real application, you
will have this as a field inside an order class or something like that, which you will get from
a database or something. So, let's do that. Let's create a class; call it "MyOrder." We will give it
the field of the "orderID," and we'll also give it a final "orderStatus enum" name that our "status."
This will hold the status of our order. So, we'll create the constructor for that, and we'll also
create an instance of this class right in here. We will create another field inside here. I think
we'll implement the "copyWith" method right there, and I think for now, that's about it. Let's see
how we can use this in our widget. We'll create an instance of the "Order," which I realize
now is very redundant, and then we'll use this to just replace our "orderID," for instance, and
we'll also track our "orderStatus" based on that order as well. Let's just make this look nice.
Awesome. Do a hot restart, and that's what we get. I think we'll move our order inside to the build
method so we can get that on hot reload as well. Let's now deal with the active state of our
cards right here. So, these cards represent our statuses. That means that the order can only
be active if our "orderStatus" is equal to that status. For instance, we'll do "orderStatus is
equal to processing" for processing to do the check. And right now, the status is processing,
so we get processing. So, let's do a "copyWith" method and change our status to something like
"in transit," and we get it active. But now, the new problem is that the previous statuses
are now not active. How do we then deal with this? Firstly, we will comment this out because I
don't think this is the most efficient way. What we will do is we will spread over the values of
our "orderStatus enum." We get that as an array, and then we will map each one of the values to an
"OrderStatusItemView," which is our "orderStatus" card. All of these will be: `e.color` will be
`e.title` and `e.description` for that, and the icon will be `e.icon`. Show line, we'll deal with
that in a little bit. For now, let's make that true. Whether or not it is active, to get back
to the last point, we'll just copy that and paste that there, and we'll compare that to the current
iteration value, which in this case is `e`. To deal with "show line," I think it's the easier
one to deal with, but I think we will need an index because we will need to just check if this
is the last item in our list. To do that, we will have to convert our map to an indexed map because
we need an index value. The map index comes from the collection package in Dart; that's already
in there, and it's very handy in situations like this. We will check if our index is less
than the "orderStatus" enum values' length, meaning the length of our array minus one. As
you can see, that is looking pretty good so far. But we're still dealing with the active state.
How do we then solve this one? In my case, it's a little bit of an easy fix because the way
my states or my values are stored in our enum, they are arranged in a way that the app will
actually flow. So, I can easily find the index of my "orderStatus" and compare it to the current
index. If it is greater than or equal to the current index, then we want this to be active;
otherwise, we have not reached that status yet, so it will be inactive. And that seems
to be working perfectly fine. And yeah, this is how I would do it. I hope you guys
have found this video very insightful, and we've mitigated a lot of code; we've got rid of a
lot of code. In fact, we can add another status in here. Let's call that "packaging" or something,
and we will change the color to something like an indigo or something like that, change the
title to "Packaging," and the description to "Your order is being packaged." Change the icon
to whatever icon you want to change that to, and it's already active because our status is
"delivered," and we didn't have to touch any UI code; we just messed with our enum. The order
of our values matters. And there you have it, folks, a quick overview of enums in Flutter
development. We covered the basics; we added some additional functionalities; we hinted
a little bit about enhanced enums. Remember, enums can simplify your code and make your
app development process way easier. If you found this video helpful, don't forget
to like, share, and subscribe for more Flutter development tips and tricks.
And let us know in the comment section which method you prefer using.
The getters in your enums or do you like using the enhanced enums definition.
Thanks for tuning in to Creative Blaq, where development meets Creativity.
Until next time, stay creative!