Instructor: So let's now come to the end of this project,
and that involves the possibility to drag and drop
a project which we have in one of the boxes,
for example, in the active projects box
into the other box.
So, to basically switch the project from being
an active project to being a finished project.
So, it's also not just about the visual update
it's not just about dragging and dropping it
and updating the UI, it's also about adjusting
the data behind the scenes in our state management class
the project state where we manage a list
of projects in the end, keep in mind
that every project does have a status property
and we'll need to update that as well.
So, two things we need to implement: drag and drop
and then all of this behind the scenes state
and data update.
Now let's start with drag and drop,
and for that we will basically implement drag and drop
as we would do it in vanilla java script
which you, for example, can learn about
in my complete java script guide.
Basically, it's all about implementing a bunch
of event listeners and of course you will see
how it works in this module in the next lectures,
but we'll implement it in typescript style,
so we'll enhance it by using some typescript features.
So, let's get started and how do I want to enhance it
with typescript features?
Well I want to reuse interfaces here.
Drag and drop interfaces,
but not just to define the structure
of some objects as we previously used interfaces
but instead to really setup a contract
which certain classes can sign
to force these classes to,
to basically implement certain methods
that help us with drag and drop.
To be precise I'm thinking about two interfaces,
and of course, using these interfaces will be optional
but this will allow us to, well,
basically provide some code that forces a class
to implement everything it needs
to be draggable or to be a valid drop target
which if we were building a bigger application
could help us write cleaner code
and more understandable code, especially
when working in a team.
So, which interfaces am I talking about?
I want to have one interface,
which I'll name draggable,
and I'll have a second interface
which I'll name drag target.
My idea here is that we can add
the draggable interface to any class
that renders and element which can be draggable.
In our example, that would be the project item class.
The project item class is responsible
for rendering, well, these project items
and these should be the draggable pieces,
and the boxes, active projects and finished projects,
so here our project list class should be drag targets.
Now, what do these interfaces force to be implemented
or to be added to the classes then?
Let's start with draggable.
Here, we basically need two event listeners
and therefore two handlers for these events.
A drag start handler, which will be a method
and a drag end handler,
because when implementing drag and drop
the thing which you want to drag
will require some listener that listens
to the start of that drag event
and also, potentially a listener
that listens to the end of the drag event
so that can do any kind of updates there
which you want to do.
Now, the drag start event handler
will get an event object which we
will have called drag event, that's a built in type,
types with options libs, because of our TS conflict setup
and the libs we're adding there
and it will not return anything
it will be a method which executes
but which then just does something,
configures the drag event for example,
but does not return.
Now the drag end handler gets a similar event,
it also gets a drag event and it all returns nothing.
Now, of course you will see how we apply those
in just a few seconds, so bare with me.
Now, what about the drag target?
Well, for the target, so the box
onto which we can drag something
there are three event handlers I want to implement.
A drag over handler,
a drop handler,
and a drag leave handler.
Now, what do these things do?
Now, you need to implement a drag over handler
when implementing drag and drop in java script
to basically signal the browser in java script
that the thing you're dragging something over
is a valid drag target.
If you don't do the right in the drag over handler,
dropping will not be possible.
You need the drop handler then
to react to the actual drop that happens,
so if the drag over handler will permit the drop
with the drop handler will handle the drop
and then here we can update our data
and UI for example and the drag leave handler
can be useful if we're, for example,
giving some visual feedback to the user
when he or she drags something over the box
for example, we change the background color
well if no drop happens and instead it's canceled
or the user moves the element away we can use
the drag leave handler to revert our visual update.
Now, all three handlers all receive a drag event
and don't return anything,
so let's update them appropriately like this.
And also for this last handler here.
And now we configured some interfaces
which on their own don't do much,
but now we can use them and I want to start
with the project item.
So let's find our project item class for this
here's the component, here's the project item,
and now you might remember that an interface
cannot just be used to define a custom object type
but that you can use it as a contract on a class.
You can call implements, or add implements here
after your class name
and after potential extensions you are doing
and then implement the interface.
In this case, the draggable interface.
Now, when you do so, and I just formatted this
to bring it in a new line to make it easier to read.
When you do so, you get an error now
that that the class here incorrectly implements
the interface because that draggable interface forces us
to add two methods, if you remember.
So, let's add them here.
Maybe we'll load a constructor.
Let's add a drag start handler
which gets an event of type drag event
and let's also add our drag end handler
which receives our drag event.
And now we have these two methods added.
Now, that alone does not enable drag and drop.
It just helps us write draggable components
or draggable classes in a uniform way,
so if we add more and more classes
which should be draggable, we always will have these methods
which simply makes it easier to reason about our code
and to work our code, especially when working
in a team, because everyone knows where to put
in work for the drag start event.
Now what this does not do, of course, is listen
to a drag start event.
That's something we can do in the configure method
which you already have though.
We can reach out to our rendered element
and add an event listener to it
and there, that would be the drag start event.
The drag start event is one event,
one default browser dom event you can listen to
and the even handler we want to trigger,
of course, is the drag
start handler, at which we can point here.
Now, we also want to be sure that
inside of the drag start handler
that this keyword refers to our class
and as you learn with event listeners
that would by default would not be the case,
so we could use bind here and bind this
that would be valid, but we have a better way actually.
We added out auto bind decorator
so I'm just going to add this here
to the drag start handler.
Now, we can also listen to the drag end event here
and point at the drag end handler.
You can also add auto bind there
if you plan on using the vis keyword here
for the moment I will just log drag end
in here so that we see that is triggered
because here I actually have nothing specific I want to do
with it and therefore I will also blank this parameter
and basically tell typescript that I'm not using it.
Here in drag start, we will use event
and for the moment, I'll just log the event,
when this event occurs.
Now, that alone won't do the trick though.
If you save everything
and you add some project here,
you'll see that you can't re-drag it, right?
If you try to drag it, that will not work
because you'll also need to change something
in your HTML file.
On this list item, which is getting rendered
for every project, which is the thing you want to drag,
you have to add the draggable attribute
and set this to true.
That is important.
This tells the browser that this will be draggable.
With that, if you saved it, and you re-add a project here,
you see now, this indeed is draggable,
it now is stuck to my mouse
and now we can really move it around here just fine.
You'll also see on the right that a drag event fired
when I started dragging and if I let go, you'll see
the drag end event also fires.
So our listeners are connected
and we can drag, now we can work on the drop target
so on the box where this should be draggable to,
to then add the project to that box.
One this I will also do real quick
is in the apps.css file, on the list items,
so on projects LI, I will add a background color
of white simply so that we can see this a bit better.
So here, project LI, I added the white
so that when we do drag around the project here,
we do have the white background here
so this makes it a bit easier to see.
Doesn't change our next step though.
We want to make his dropabble.