Speaker: Welcome back.
In this lecture, we are going to build the search controller
and in order to do that,
you will learn about the concept of application state.
And then you will learn a simple way
of implementing state in our app.
So let's open up index.js which is
where we're gonna put our controller.
So again, each model and each view will get it's own file
for each of the functionality.
But for controllers, I'm going to put all of them
into the same file because that's make it a lot easier
as you will see when the file gets bigger and bigger
as we adding more controllers.
And it will be easier to have them all in one file, okay?
So let's now talk a little bit about something called state.
So imagine our final app running with all the
search queries, the recipes, the likes, the shopping list.
So what is the state of our app in any given moment?
So think about what is the like the current search query?
Or what's the current recipe?
Or how many servings are currently being calculated?
And what's currently in the shopping list?
So all few things in one given moment are the state.
So all these data in the current state
in a current moment of our app,
all of this data is the state and we want
that to be in one central place
like one central variable like an object
in which we have then,
basically all the data that defines our app
in a given moment in one place in one object, okay?
So that's what we're going to implement now
and it's actually very easy at least
in our very simple app like this, okay?
Now their entire library is for state,
maybe you've heard of Rudex
which is used together with the React
so that's a very popular state management library.
But in this case, we will just do something very simple,
just one object which is the state of our app.
And Redux this is like the store, it's called store
but let's just call it state here, okay?
So const state,
and for now it's empty.
And let's actually add a comment here.
So saying the global state of the app.
And in here we will have ...
The search object so all the data about the search
which we actually already coded up in the last lecture.
So remember in the search object is
where we have the search query and the search results
and so that will be part of our state.
Then we want the current recipe object.
So that will be later when we're talking about recipes.
Then we also want to go shopping list object
and we want the liked recipes, okay?
And so again, all of these data will be stored at all time
in one central variable which we can an access
throughout our controller, okay?
So instead of having many variables like
having the objects store in some place,
in some variable or having the recipes like hidden
from other functions, from other scopes,
we have everything in one place accessible
to everything inside of this module, okay?
So that's a pattern that I really like to use,
and it's really helpful in this case.
So again we start with an empty object here.
So each time that we reload the app,
the state will be empty.
And we will actually make some
of the state persistent a bit later which means
that when we reload the page then the state
or some part of the state can actually persist,
so it can be saved but let's save that for later.
For now let's start implementing here part
of the controller for the search.
And the first thing that we're gonna do is to actually
add an event listener for the search forum, okay?
So basically for this button and for this entire form.
So let's take a look at their html,
and it is up here so the form
that we're looking for is this one here called search.
So let's now add an event listener
for whenever we submit this form, okay?
And event listeners are something that go
into the controller because that's where
we're then gonna delegate what people want to happen
when these are submits to form, right?
So document
.querySelector.
addEventListener.
And event we're looking for is the submit event.
And then of course, our callback function
in which we pass the event object into, okay?
And let's see what actually happens right now.
So when we click this here,
you see that the page reloads, right?
So let's take a look again and we don't want that to happen.
And so we say e.preventDefault, right?
So we did that before of course.
And then we can now also create a new function that you want
to be called whatever the form is submitted, okay?
So instead of putting all the logic here
inside of this callback function,
let's make a clean new separate function from this, okay?
So controlSearch.
Okay, so no arguments here.
All we want to do is to put this code basically
outside of this callback function here,
make a nice separate function just for this, okay?
So whenever we submit the form,
we prevent the default from happening
and then the controlSearch function is called.
And now let's think what we want to happen, okay?
So I will actually make now a bunch of comments,
listing each of the stuffs that must happen here
in this search controller, okay?
So the first one is that we should
get the query from the view.
So let's call this simply query
and I will simply add a place folder.
And say that we shouldn't do this later, okay?
Because in our view module, we will have a function
that will get the search query
from the other interface, okay?
Of course we could put this right here,
we could now do a document query selector
and then read that data right from the user interface
but that's something that has to do more with the viewer.
And so we're going to put a method for that
or a function into the search view module, okay?
But we're gonna do that in the next lecture
so that we have one lecture for each
of these different parts of the architecture, okay?
Right now we're talking about the controller
so let's leave it like this for now
and then come back in the next lecture.
And curl all of these functions for the view, okay?
Now if there is a query,
we then want to create a new search object, right?
So let's say if ...
Query so if there is a query.
Then what we want to do next is
New search object and add it to state.
So let's do that.
So state.search will be a new Search object
with the query, right?
So similar to what we did here but now this time around,
we are actually going to store it here
into our global state object.
So this one that we just talked about
in the beginning of the video, right?
So let's get rid of this here.
And next, what should we do next?
Well, we can now prepare the user interface
for what's going to happen, okay?
So like clearing previous results or show a loading spinner,
and so that's what we're going to do here as a next.
And again, I'm leaving that for the next lecture but
that's one of the steps so I'm putting it here right now.
Next up, let's actually do the search so search for recipes.
And so that's where this method here comes in.
So on our state
.search object,
we now can perform the getResults methods, right?
So again state.search is where this all list
so this new instance based on the search class.
And on that, we of course have
to getResults methods available,
so that we can then later display these results
in the user interface.
And actually that's exactly the next step,
so render
results on UI.
Okay, now of course we only wan this here to happen
so we want the rendering of the results only to happen
after we actually receive the results from the API, alright?
And so what we do have to do here is
to actually await this promise, right?
So simply use await here.
Now we need to say that it is an async function,
and we do that right here, right?
Because this here is where we define the function.
And so we say async function
so that we can enuse await in here.
Okay, Make sense?
So again, this here returns a promise, right?
And why is that?
Well let's open up the map out here.
So this is an async method.
And remember that every asynchronous function,
it automatically returns a promise, okay?
And so here, we then have to await.
So until the promise results,
n comes back with our data, okay?
Now we're not really going to render results on the UI,
but what we can do here is then
to lock these results to the console.
So console.log and where are these results actually stored.
So they are in state.search.recipes, right?
Or is it result?
I'm not really sure.
Oh yeah, it is result, you see.
So it stores it into this .result,
and so here is then state.search.result.
And let's actually get rid of the console.log,
oh we already did that so the only console.log
that we have is going to be this one here, okay?
And so what this means is that the getResults method runs
and we wait for it to finish basically.
And only after that is done we can then log to the console,
the result here, okay?
And so with this, we can test if this async await
here is actually working as intended.
So let's test it out.
And we don't actually have to input anything here
because again it's not really being read right now.
Right now we're just using the input pizza here
as a temporary query, right?
So let's just hit search here and let's wait for it.
And indeed, it did cam back with our data here.
And it's all on pizza, right?
And you can see that this console.log from index.js line 27
which is exactly, well it's not this one here
but I guess the line numbers must correct
because of all the web pipe blending
that stone behind the scenes
but it's pretty much the same 25, okay?
So that is really all there is to control right now.
So all we have to do now is to actually implement or view
so that we can get first the query from their view
that we can then prepare the user interface
for the results like having that spinner.
Clearing the input maybe.
And then finally we want to also render these results
on the user interface of course
instead of just logging it to the console, right?
So if you're ready to do that,
then just come with me right to the next video.