-: So let's now learn how we can listen for events
and also handle events in our MVC architecture
by using something called the Publisher-Subscriber pattern.
And let's start by analyzing the code
that we already have here.
So right now we are listening for the hashchange
and for the load events right here in the controller.
However, that doesn't make a lot of sense, does it?
Because everything that is related to the DOM,
so to the view, should really be inside of a view.
Now, maybe these two events here don't really look
as if they have to do with the view,
so with the user interface.
But imagine that instead we would be handling a click event
on some DOM element.
And so listening for that event should for sure,
go into the view.
And therefore, we can say the same about these events here.
So in the end, this has more to do with DOM manipulation
or what to DOM itself then actually with the controller.
And so therefore, we need a way of putting this logic here
into a recipe view.
However, the handler function that we use
to handle these events is actually this controller.
So it's this function that we have up here
that is sitting inside of this controller module.
And so we have basically a problem here.
We don't want this code to be here
so we want it to be in the view.
But in this code, we need this controller function
which is here in this module.
And of course, we don't want
to put this function in the view.
And so let's now think about
how we could solve this problem.
And recapping everything that I just said before,
we can basically say that we want to handle events
in the controller because otherwise,
we would have application logic in the view,
and of course we don't want that.
But on the other hand,
we want to listen for events in the view,
because otherwise we would need DOM elements
in the controller,
and we would basically have presentation logic
in the a controller which would be wrong
in our MVC implementation.
So essentially, event listeners should be attached
to DOM elements in the view,
but the events should then be handled
by controller functions that live in the controller module.
And so if you take a look at this small diagram
that is just a part of the architecture diagram
that we already saw before,
so here we have to controlRecipes function
in the controller,
and we have a special method in the view,
which is called addHandlerRender.
Now, we might think that it is very easy to connect
these two functions
because why not simply call the control recipe's function
right from the view whenever an event occurs?
Well, that's actually not possible
because in a way we set up the architecture,
the view does not know anything about the controller.
So it doesn't import the controller,
and so we can't call any of the functions
that are in the controller from the view.
So it only works the other way around
and therefore it's more complex than this.
But fortunately, there is a good solution and this solution
is called the Publisher-Subscriber Design pattern.
And by the way, design patterns in programming
are basically just standard solutions
to certain kinds of problems.
So in the publisher-Subscriber pattern we have a publisher
which is some code that knows when to react.
And in this case,
that's going to be the addHandlerRender function
because it will contain the addEventListener method.
And therefore, it will know when to react to the event.
Now, on the other hand, we have a subscriber
which is code that actually wants to react.
So this is the code that should actually be executed
when the event happens.
And in this case, that is the controlRecipes function
that we already have in our controller.
And remember that the publisher does not know yet
that the subscriber even exists
because that subscriber is in the controller
that the view cannot access.
Okay.
But now finally comes to solution to the problem.
So the solution is that we can now subscribe
to the publisher by passing into subscriber function
as an argument.
Now in practice, that means that
as soon as the program loads, the init function is called
which in turn immediately calls
the addHandlerRender function from the view.
And that is possible, remember, because the controller
does in fact import both the view and the model, right?
Now, anyway, as we call addHendlerRender,
we pass in our controlRecipes function as an argument.
So essentially, we subscribe controlRecipes
to addHandlerRender.
And so at this point, the two functions
are basically finally connected.
And so now addHandlerRender listens for events
using the addEventListener method as always.
And then as soon as the event actually happens,
the controlRecipes function will be called
as the callback function of addEventListener.
Or, in other words,
as soon as the publisher publishes an event
the subscriber will get called.
All right.
And this is how we implement event listeners
and event handlers in the MVC architecture.
So this will allow us to keep the handler in the controller
and to listener in the view.
And by that, keeping everything nicely separated.
So in summary, the handler subscribes to the publisher,
which is the listener in this case,
and then as the publisher publishes an event,
the subscriber is executed.
And if you want to think even deeper about this
and are really interested in this,
then notice how there is actually a profound difference
between a certain arbitrary like function A
simply calling function B directly
and function A receiving function B as an input
in order to then call that input function.
So this is all about control.
In the first scenario, function A is in control.
However, in the second scenario function A has no control.
So it simply has to execute whatever function it receives.
So if you want, reflect a little bit on that
and see that this is exactly
what the Publisher-Subscriber pattern is actually all about.
But anyway, leaving that theory aside now,
let's go back to our code and implement all of this.
And so with everything we just learned
about the Publisher-Subscriber pattern,
actually, now implementing it
should be the easiest part, right?
So let's simply grab this code.
So cutting it actually
and then here we will create a new method
and let's just put it somewhere, let's say here.
And so this will be our addHandlerRender method
that we just talked about.
So addHandlerRender because this is going to be
for rendering the recipe right at the beginning, right?
And then this method, which remember, is the publisher
basically needs to get access to the subscriber.
And so that in this case is the handler function.
All right?
And so then we can simply paste that in here.
And then here, of course we don't know about controlRecipes,
but we know about the handler.
And so that's actually it for this function.
So of course it is not a private method
because it needs to be part of the public API of this object
so that we can then call it in the controller, right.
And so let's actually do that now.
So we can get rid of this now.
And we will want to do this right in the beginning.
So let's create an init function here,
actually like this,
and then we simply call it right at the beginning.
So only once.
And actually we could simply put all the code
also here in the global scope,
but I think it's a bit cleaner
to have a separate function for this.
That's recipeView.addHandlerRender.
And so now we simply pass in controlRecipes,
and that's actually it.
With this, we just implemented
the Publisher-Subscriber pattern.
For some reason, we're still getting these errors here.
Let's get rid of this alert here actually,
and simply do a console.log here.
Okay.
But now let's go and see if this actually works.
We're still having our slow network.
Oh, and here we have some problem apparently
with the timeout.
So let's go quickly fix that here in the helpers.
So we saw that here it said undefined,
like after undefined second.
So maybe this variable here doesn't exist.
So maybe it's misspelled.
So let's see in the config.
Well, it looks right.
Yeah, it is the same.
Well, let's see again.
And so this apparently happens immediately
for some reason here.
So what if we put it back to some normal number?
Well, then it works, which is very weird
because this is in fact also 10.
So let's see what we get here as we lock timeout seconds.
Oh, I'm actually right now seeing the problem.
So this is not helpers, it is config.
So we are importing ourselves here.
So that was the problem.
Let's put everything back.
And you see that now it is working.
Even with the hashchange event.
And so that means that we did now successfully implement
the Publisher-Subscriber pattern.
Okay?
And so let's quickly recap what exactly is happening here.
So we can also take a look at our final diagram here.
And here, I actually have the event here in the controller
because that is actually where it is handled.
And so I think that in this diagram,
this makes it a little bit easier
to actually understand the flow of the program.
So anyway, as we start to program
then the init function runs
and it will then immediately run addHandlerRender, right?
So it is this function here.
And it's this function that is actually
listening for events right here in the view
where it actually makes sense.
Now, as we call this method here, so in the controller,
we pass in the controller function or the handler function
that we want to get executed as soon as the event happens,
right?
And here we then receive that function
as being called handler.
And so that's what we then call
as soon as the event happens, right?
And so again in our diagram,
that's exactly what we have here.
So that's why I have this dotted line here
which stands for data flow.
So we are passing in the controlRecipe function
as the handler here.
And that is the whole reason
why the method here is called addHandlerRender.
So because we are using it to, in fact,
add a handler function and in this case,
it is for rendering the recipe in the first place.
And then later on,
we will actually have other addHandler methods.
Okay?
And so it's crucial that you understand this logic here
before you can move on any further in this project.
But I hope that with all this explanation,
this became all really clear
and also obvious why we had to do it like this.
I mean, of course we don't really have to do it,
so we are, of course, in charge of our own code.
But in order to correctly implement the MVC architecture,
this is the best way of doing it.
And so again, then we can keep everything nicely separated
into a model controller and view
without any overlapping responsibilities.
All right.
So we have all of this structure here now nicely set up,
everything is nicely separated.
And so from now on, all we have to do
is to basically use this structure to implement
all of the missing features off our application.
And so again, really make sure that you understand
everything that we did so far,
especially regarding the implementation of our architecture.
And then once you are really done with understanding that,
let's go straight to the next video.