Jonah: So, as I just said,
let's now start with the feature of uploading a new recipe
and start with the ability of opening the model window,
which contains the form to add the new recipe.
So in the demo version, this is what it looks like.
So here we click add recipe,
and then it opens up this form like this,
and then when we click this button,
or click outside of the form,
then that window will again close.
Alright, so let's do that,
and let's create a new bookmark's view.
And actually not a bookmark's view,
but a addRecipeView.js
And now let's go to one of these views,
and copy the code from there.
Because this code is always very similar,
so let's delete this one here,
let's empty out this method.
And then here, let's call it AddRecipeView.
Now this view here is actually gonna be quite different
from the other views because we already have
actually the view in the HTML.
So if we come here to our HTML code,
then you see that the form that we want to display
is actually already here in the code, all right?
So, here we have this element for the overlay
and this element for the window
and they both have the hidden class.
And so showing the window and the overlay
is gonna be as simple as removing this hidden class
from both these elements.
Now, the main element that we are actually
really interested in is this upload element.
And so let's actually make this upload element,
the parent element of the AddRecipeView.
So upload here, but then we will also have
to select some other elements.
So for example, the window and the overlay,
so to start at least.
So the window element is going to be document.querySelector
and then let's see what we have here.
Here we can close all of these for now.
So that's add recipe window.
And then the overlay has simply the overlay class.
And so here, overlay and here as well.
And here we are missing the dot on both selectors.
And now we also need to select a button
that will be clicked to open the window
and also the button to close the window.
So that button is somewhere here in the top navigation bar.
So this is for the bookmarks and here it is.
So this is the button for adding the recipe as you see.
So let's call that the btnOpen
and then also the button to close the form.
And so that's back here somewhere in the window.
So that's btn-close-model.
Okay, and here.
Okay and so now, let's listen for the events,
so of clicking the open button and the close button.
Okay, and as always, we will do that in a method called
addHandler and then something,
just to make it more consistent.
So addHandlerShowWindow, let's say,
and so here we will want to select the button.
So btnOpen.addEventListener of a click.
And so when that happens, what do we want to do?
Well, we want to take the overlay into window
and remove the hidden class.
So that's this.overlay.classList.rem.
Now, instead of remove, we can actually also use toggle.
So remember that toggle will add to class if it's not there
and it will remove the class when it is already there.
And so this will make it a lot easier
to then reuse this class.
So the overlay and also the window.
Okay, now, when do we actually want
this function here to be called?
Well, we want this to be called as soon as the page loads.
Now, in this case, this has nothing to do
with any controller because there is nothing special
happening here that the controller needs to tell us, right?
So when this click happens on the button open,
all that will happen is really for the window to show.
So the controller, it doesn't need to interfere
in any of this and so therefore we can simply run
this function here as soon as this object is created.
And so what I'm gonna do is
to this time add a constructor method,
then since this is a child class,
we need to start by calling super.
And so only after that, we can use the this keywords.
And then let's say, this.addHandlerShowWindow.
And so this one here is now only gonna be
used inside of this class.
And so let's add an underscore to mark it as protected.
And so again, in order to show this window,
the controller does not interfere at all, all right?
Now what we will have to do in the controller still
is to import this object here
because otherwise, our main script sort of controller
will never execute this file.
And so then this object here will never be created.
And so the event listener here will never be added.
And so we need to, again, import this
so that the code that is in the module
is actually being run.
So here let's call that the AddRecipeView.
And now let's check out our code
just to make sure we reload it.
And we got a class list of undefined.
So some small bug here, and again,
you see how common that is.
So let's again, see which line that actually was.
So line 19.
So with the overlay.
So let's see if the class is correct.
Well, it looks so.
No, but I can see the error now.
So here we are using the this keyword
inside of a handler, right?
But you already know that the this keyword
inside of a handler function points to the element
on which that listener is attached to.
So in this case, that is this button here.
And so let's actually export this entire function
into another method and then call that method
with the correct this keyword bound to it.
So here is what I mean, toggleWindow, let's say,
will do this and then here,
we want to call this.toggleWindow.
And now here we can use our bind method as always,
and then bind the correct this keyword.
So we have done this many times before,
so basically manually setting the this keyword
inside of this function here,
now to the this keyword that we actually want it to be.
And so right here, this of course,
points to the current object
because otherwise, again, the this keywords
inside of this function would be the button
on which the event listener is attached to.
And so with this, it should now work and yeah,
there is our form.
And now, all we have to do is to close that form
when we click this button or click outside here.
So addHandlerHeightWindow.
And so that's actually very similar to this one,
that's just duplicated actually.
So btnClose and then the same also on the overlay.
And so that's why this toggle here
is now very useful because here at this point,
when we want to hide the window,
then the hidden class is no longer there,
but it will then automatically add it back on.
Now, and before we actually try it,
we first of course, need to call this method here as well.
Okay, and it's gone.
Great, so that works.
And so next up, let's take care of handling this button here
and for now what we want to do
when we click this button is to get all the data here
out of this form.
And you see that I already have like,
pre-filled this data here.
And so that comes from the HTML here
because the value is basically already set.
But then of course, by the end, we will remove this.
So this is just for development purposes.
But anyway, let's now create another method here,
which is going to handle the click on that button.
So basically the form submission.
So addHandlerUpload.
And so here we will now actually listen for an event
right on the parent element.
So that is the upload form itself.
So parentElement.addEventListener
for submit and then inner function as always,
the first thing is to prevent default.
So here we need access to the event, prevent default.
And now how do we get access to all of these values?
Well, we could go ahead and select
all of these form elements one by one,
and then read the value property of all of them.
However, there is actually an easier way
because we can use something called form data.
So that's a pretty modern browser API
that we can now make use of.
So let's say data equals
and then we can create a new form data
and into the form data constructor,
we have to pass in an element that is a form.
And so that form in this case is the this keyword, right?
Because we are inside of a handler function.
And so this points to this.parentElement,
which is of course the upload form.
Now this here will then return a weird object
that we cannot really use,
but we can actually spread that object
into an array, like this, all right?
And so this will then basically give us an array,
which contains all the fields with all the values in there.
So let's then lock that data to the console.
Now let's think what we actually want to do
with this data eventually.
So this data right here is the data
that we eventually will want to use to upload
to the API, right?
And that action of uploading the data is going
to be just another API call, right?
And where do API calls happen?
Well, they happen in the model.
And so therefore we will need a way of getting
this data to the model.
So just like we did many times before,
we now need to create a controller function,
which will then be the handler of this event, okay?
So let's come down here and create controlAddRecipe.
And so this function here will then actually
receive the new recipe data.
And let's actually have this one here
lock the data to the console.
So newRecipe, okay?
And now all we have to do is to say,
addRecipeView.addHandlerUpload
and then controlAddRecipe.
So this is the publisher subscriber pattern
that we have used many times before.
And so eventually here we will have some function
to then upload the new recipe data, okay?
And so here we now need to accept
this handler function and then we need to call it.
So instead of logging it to the console right here,
we will simply call the handler function
and so this handler function will then for now log it
to the console because again, that handler is now
this controlAddRecipe.
All right, so let's see what happens.
And so that's why I have all of these prefilled data now,
so that we can simply click the upload button
and then get our data down here immediately.
So let's now take a look at the data.
And so since we got that data, it means that everything
is correctly set up, which is great.
And so here we get the array of multiple erase in there.
So basically the entries of this form,
where the first element is always the name of the field
and the second one is the value.
All right, so title, source URL,
and you see all of them here, okay?
Now usually, our recipe data is always an object
and not an array of entries like this.
And so in JavaScript, since IES 2019,
there is now a new and very handy method that
we can use to convert entries to an object.
So let's actually call this one here, dataArray.
And then the data itself is gonna be object.fromEntries
and then the data array.
And so this fromEntries method here
is basically the opposite of the entries method
that is available on erase, right?
So this one takes an array of entries
and converts it to an object.
So let's see what that looks like in practice
and beautiful, so this looks already a lot more
like our original recipe object,
like this one here for example,
it is of course still missing some formatting
and it is still missing some data like the ID,
but that we will take care of in the model.
And so let's go do that in the next video.