- [Instructor] In this video,
we'll continue looking at managing dynamic CSS with Vue,
this time through the use of class attribute bindings.
And you can see that we're back
to our flashcard presenter again.
What a good flashcard app needs
is a way to receive feedback from the user.
At the very least, the user
should be able to say either I'm good
with this card for now
or show me this one again in a bit.
So let's add a couple of buttons for that.
We're going to end up putting them right on the back
of the card
and one will say GOT IT
and the other will say AGAIN.
And we'll put them in a div with class score
just to help with the layout a little bit.
I'm also going to take this v-else here
from the div with the back content
and create a parent element
for both of these elements
so that they're toggled at the same time.
The back content, along with those buttons for the feedback.
One problem with our implementation so far
is that the card changer logic just sort of stops
when we get to the end of the array
and then we can only go backwards.
So let's make it continue from the beginning
when we go past the end and vice versa.
All we have to do is add an else
and say if that index doesn't exist
and the user's trying to go forward
or change is plus one,
then we'll reset the index to zero.
So we'll say this.index,
depending on the value of change,
so we test for if change is one,
then we set it to zero,
back to the beginning
or we'll set it to the last index
if they were already moving backwards
and they're going past the beginning.
So this.cards.length -1
and whatever path we take,
the if or the else,
we can always unflip the card.
So let's move this line to the end.
And now let's handle GOT IT and AGAIN
with methods named for them.
No parameters necessary.
So on this button,
I'll add a click handler
and it's going to call a method named gotIt.
And on the again button,
same thing but it'll call a method called again.
So now down in methods,
all gotIt has to do is remove the card from the list
by splicing one element.
And then it can unflip the next card,
which will automatically move into the current position.
So we can do this.cards.splice,
starting at the current index,
splicing one element.
And then we can say make sure the next card
is not flipped already.
We want to be careful
if we end up removing the last card though
because then our index is no longer valid.
So after splicing,
we should add a check to see if the current index
is still valid.
So we'll say if this index doesn't exist,
then we can just reset to zero.
And if zero is also not valid
because maybe this was the last item
in the array that we were removing,
then we could just,
at the beginning, pop an alert
that says well done.
So we could test if the length of the array is one,
even before we're removing anything,
we can just return and pop an alert at the same time
that says well done.
Not pretty for now
but it does avoid these errors
and I'll leave it to you to come up with a slicker way
to handle the completion of the deck.
Also since GOT IT and AGAIN,
since those buttons are right on the card,
we don't want a button click
to cause the card to flip when that event bubbles up.
So we should stop propagation of the click event
to the parent div by just adding the stop modifier.
So click.stop and click.stop.
So we still need to define again
and in again, we want to flag the current card
as needing review.
So we can just add a new property to the card
called isRepeat and set it to true.
So this.cards, this.index,
we can say isRepeat equals true.
Speaking of repeating things,
look at how many times I'm repeating this reference here,
this.cards, this.index.
That would be a great candidate for a computed property
to clean up these methods a little.
But again, I'll leave that to you.
And in again, we still want to increment the index,
go to the next card after the user clicks again
but we should do so through the move method,
which handles the bounds correctly.
So this.move one.
Okay, so over in my style sheet,
I have this again class already defined,
which just adds a yellowish background color.
So what we can do in our card div up here
is add a dynamic class attribute,
again with v-bind or just :class
and similar to the style syntax,
this is often going to be a JavaScript object
but the property names will correspond to CSS classes
and the values will be treated as Booleans
that determine whether the class name
should appear in the list.
So if I write again
and isRepeat, I'm saying that the again class
should appear in the class list
as long as isRepeat is true
but remember, this isn't quite right yet
because isRepeat is a property of the current card
or any card.
So we would either have to change that
so we're accessing isRepeat through the current card
or to keep the template cleaner
and to leave it like this,
we can just make a computed property
that returns the value of isRepeat for the current card.
And again, I'm going to be repeating that same reference
but that's okay for now.
So isRepeat
is this.cards, this.index isRepeat
and if we've done this correctly,
after I refresh and I'm going through the deck,
I can click Got It, Got It, Got It
and if I want to see this one again,
I click the Again button
and as I'm cycling through,
when I get back to it, it's now yellow,
indicating that I needed at least one additional review
for this one.
Just like with the dynamic styles,
I can include multiple classes here
with multiple conditions.
So I could say I also want anotherClass
as long as something else IsTruthy, like so.
In the next chapter,
we'll take a look at how to clean up our templates even more
using Vue components.