Jonas: So after loading the recipe data
from or API, let's now render that data in our application.
And for that, let's go
to our HTML file to basically get the template from there.
Let's close down this terminal
which will keep working in the background.
And so here is the results part, the pagination.
And then here we have the recipe class.
So the recipe class
is basically this whole container.
So here in this case,
it's this whole gray container
which is the one that will contain
the rendered recipe.
Okay.
Then right now it has that message.
So again, it is this message here
that is already rendered there at this point.
Then here's the code for a loading spinner
for an error
and then here, actually for the recipe itself.
So here we have that, not that image,
and then all of the information about the recipe itself.
And so it's all of this code that we need now.
So let's grab
all of this commented out code
and copy it
and paste it here into this function.
So let's add a comment here.
So loading recipe
and then afterwards as step number two,
rendering the recipe.
And for now here we are doing this
like really big function.
But of course,
once we start thinking about the architecture
we will then break this up
into functions and modules
and classes and so on and so forth.
And so, as always doing a big
template literal here, just as always,
so that we can
and then replace all the data here
that we need.
Just fixing the indentation here now.
And so now let's take all the data that we need.
And the first one here is the image.
So let's replace this string here
with recipe.image.
Just like we specified here.
And so this image property
is basically a URL,
which points to the location of the image
on the Forkify API server.
Then here we have the recipe title.
So this one here,
.title.
And actually we also have that title here
as an alt text of the image.
Okay.
Then here we have the clock.
So this 45 here is the cooking time.
So recipe
and missing the block here,
.cookingTime.
Then down here, we have servings.
And so that's this number here.
So number four will now be replaced
with the data coming from the recipe object,
recipe.servings
and let's keep going.
So down here, we have the ingredients.
So for each ingredient,
there will be one list element of this.
So this example,
right now we have two list elements
and one for each ingredient.
But let's actually keep that for later.
And for now keep filling the rest
of the data here.
So this is the next piece of data,
which is the publisher.
So here it says recipe publisher.
And so let's change that
to recipe.publisher.
Then here we have the source URL.
So let's take a look at that,
maybe here to make more sense of this.
So we used most of this data here already.
So here is the URL to the recipe itself,
where it actually comes from.
And then about the ingredients,
as you see, it is one array
and each position of the array contains one object
which contains the quantity,
the unit and the description of each ingredient.
And so we will have to basically loop
over this array
and then use all of this data
to create one list element for each of them.
Okay.
But for now, let's go back
and finish the data here.
And in this case,
replacing this URL
by the one coming from the object.
So that's the recipe
that source URL.
And so except for the ingredients,
that's actually it.
So yeah, before we can check out the result,
of course now we need
to actually insert this HTML into our dump.
So for that, we can use the insert adjacent HTML method
and we need to do that
on the parent element,
remember.
And I already selected that up here.
So remember, that's the element
with the class of recipe.
So just to remember, it is this diff element.
So that is called a recipe container.
And so that's where we want to attach
this HTML markup.
So recipeContainer.insertAdjacentHTML,
and let's do afterbegin.
So basically as a first child
and then the markup variable
that we just created
and that should be it.
So this should now render the recipe
in the user interface
except for the ingredients.
And indeed, that's looking really nice already.
Right?
So the ingredients are still the old ones
but the rest is really nice,
except for that we have still
this message here from the beginning
and also that we are missing all the icons.
So you see there are no icons to be found here.
In the real one, of course,
there are icons all over the place.
So we have three problems here.
We have this message showing
we have the ingredients
and we have the icons.
And let's start with this message
and then the ingredients.
So before we insert any new markup
we need to get rid
of the markup that is already there.
So let's simply do recipeContainer.innerHTML
and set it to nothing.
So emptying it out.
And so you see now it is gone.
All right.
So let's now worry about the ingredients.
And again, we will need to loop
over the ingredients array.
And for each of them,
we should then create this kind of markup here.
So how should we do that?
Well, basically exactly what I just said.
So we take recipe.ingredients
and then we loop over that using some array method.
But what array method should we actually use?
Well, remember that in the end
the expression that we need here
needs to return a string of HTML.
And so that means
that or array method needs to return something.
So foreach is not the way to go here.
So not foreach.
Right?
But instead we are going to use map.
So map returns a new array
with the same length.
And so that array, we will then in the end,
be able to simply join.
And so now we can loop
over the array
by specifying a callback function.
So each element is going to be called ingredient
and then here we can do something.
So let's simply replace a string here.
Right?
So taking this
and put it right here.
And then of course we don't need
this one anymore.
(clicking)
Okay.
Then here we have some kind of error,
but nevermind.
Let's think about the data here first.
So let's take a look
at the data actually again.
So at the array.
So each array element is an object
which has quantity,
unit and description.
Okay.
So this ingredient is now that object.
And so here we can say
ingredient.quantity
then here the unit,
the ingredient.unit
and then finally here
instead of pasta we want
the ingredient.description.
And so now here
we will have an array
in which each element
will contain this markup corresponding
to the ingredient.
And so now all we need to do
is to transform that array of strings
into one big string.
So we can take the result of this map,
which is that array
and call join on it like this.
And so now the result of this entire expression
is going to be
a big string containing all the ingredients.
So if we give it a save now,
then indeed here we have our eight ingredients.
Okay.
So that's pepperoni pizza burgers.
And now,
remember we have a second one here,
so that's, switched them out again.
Give it a save.
And now we got,
well, this pizza here.
And so indeed it now has different ingredients,
different publisher
and everything is different.
Great.
But now there is one thing missing,
which is the icons.
So let's see why that is.
Well, remember that the page that
is displayed here in the browser,
is this HTML here from the disc folder.
Right?
And so remember that all the images
and really all the assets
are now coming from this folder.
And that includes the icons.
So our icons are always coming
from this icon.svg file.
But now the icons are actually coming
from icons.all of this here.
And you can see that
for example,
right here in the search bar.
So icon search is coming
from icons.96 and so on and so forth.
However, in our template literal,
we are still writing, basically,
the old path to the icons.
So this one here.
And so right now,
JavaScript will not be able to find this.
So in the disc folder,
this one here,
there is no source/image folder
in which there is icons.svg
because that exists only
in our source folder.
So only right here
where we are developing the application.
But again right now
we are basically shipping the application already.
And so it's using the data from this disc folder.
And so now we need a way
of telling our JavaScript
that the icons file is no longer this one
but instead it is this one.
And we can actually do that
with parcel by basically simply importing
the icons file.
So let's go to the top of our file
because I like to keep all the imports
always at the top.
And so again, in parcel,
we can import more than just JavaScript files.
We can import all kinds of assets
and that includes images.
So let's import
and let's call it simply icons.
But this name can be anything that we want.
(clicking)
From another path to the original icons file,
basically, from the view of this controller file,
right?
So here we are in controller.js.
And so now we need to find a path
to the images,
so to this original icons file.
So we need to go one way up.
So exactly the way we browse
the file tree in the terminal.
So .. always means the parent folder.
And so right now we are back
in the source folder,
which is the parent of js.
And then from there,
we can go into images
and then icons.svg.
All right.
Now this is the way it used to work
in parcel one.
So if for some reason,
you are running parcel one
then this is the way to go.
But in parcel two,
it works almost the same way.
But then for any static assets
that are not programming files.
So for any like images
or videos or sound files,
we need to write url:
and then the path to the file.
Okay.
So let's take this out
but then let's lock this icons to the console
so that you see what this icons really is.
Because in fact, it is nothing more
than simply the path to the new icons file.
So the local host,
one two, three, four
is in this case, basically,
our disc folder.
And then in there,
the file that we need is icon.96f
and so on and so forth.
And so that is exactly this file here.
Okay.
And so now let's use that.
So everywhere it says icon.
So everywhere we have this old path
we now want to replace it simply with the icons.
So let's select all of them using command
or Control+D.
Or if that doesn't work for you,
you can always probably use Command+F
or something like that.
But anyway,
now we have all of them selected at the same time
and then I can delete them all
and then insert the icons variable here everywhere.
And so now if we give this a save
then our icons are back.
Right?
So starting here
then in all ingredients
and here also,
all over the place.
We now have our icons back.
And now just to finish this lecture,
I want to give this one more touch,
which is this here.
So watch what happens here
in the recipe when I load the page.
Well, that was pretty fast.
Let's see again.
So maybe for half a second or so
you saw a loading spinner there.
And so that's what I want to have here as well.
So before the recipe arrives
I want like a loading spinner there
because that's a very common pattern
that you see in all kinds of applications.
Right?
And it's actually very simple.
So we have the code already here
in our HTML.
So it is this a spinner here.
So let's grab this code.
And then
here I will simply create an external function
called
render a spinner
and let's make this a very generic function
that we can reuse.
And so that's passed in the parent element.
And so then we can simply attach this
to any parent element
that is passed in here.
So as always creating a markup variable
and then our code here.
And just like before,
we need to now replace this old path
with the new path.
So icons
and then of course,
we need to add this HTML
to the dump as a child
of the parent element in this case.
So parentEl.insertAdjacentHTML
afterbegin
and markup.
Okay.
And now let me just quickly show you
why this is going to work.
So here in the CSS,
let's look for spinner.
And here you see
that the icon inside of the spinner class
has this rotation animation
that keeps going forever.
So that's this infinite attribute here
in the animation property.
And this rotation animation
I created here manually using key frames.
And basically what it does
is to rotate the element
to 360 degrees.
And so if you ever need a spinner like this,
you can simply, basically copy this code here.
All right.
Let's close what we don't need here.
And probably, before we insert this,
we should also clear the parent element.
So just like before setting the inner HTML
to nothing.
And now let's actually render the spinner.
So let's do that here
as we load the recipe.
So right here.
So renderSpinner
and then the parent element in this case,
is going to be the recipeContainer.
All right, let's go back
and reload
and there it was.
You saw it.
Let's make this a little bit slower
by changing our network speed here.
So it took a little bit longer,
maybe slow 3G
is gonna be even better.
And so now it's gonna take
a lot more time
but indeed here it is.
So that spinner is a nice touch,
I think.
And it definitely makes this application
feel more real world.
Now just to finish this video,
something that I should have done
in the last video already
is to add polyfills
for es6 features
to our code base.
So just like we did
in the previous section as well.
So remember to do that,
we installed some special packages.
So the packages are called npm core-js
and we can actually install multiple packages
at the same time.
I think I never did this before.
So this is how it works.
Regenerator-runtime
and then hit enter
and then let's wait for these packages to download
and here they are.
So they should be,
yeah,
so right here
and now all we have to do
is to import them here
at the top of our file.
And so it is, we make sure
that most real old browsers
are still being supported
by our application.
So actually we don't even need to save it anywhere.
We can just say core-js/stable.
So vs code, one more time, is really smart
and can really help us
with package imports like this.
So again, this one here
is for polyfilling async/await.
And this one here is for polyfilling everything else.
And we could just cherry pick some features
and only import those
but let's simply polyfill everything.
Okay.
Don't need this terminal anymore.
This one here already reload it
and you see everything keeps working the same.
All right.
So we have this working.
Now in the next video,
let's quickly add some event handlers
so that after that
we can start talking about the architecture.