I want to start with innerHTML
and for that, let's select this section again and let's say we want to entirely change its content.
So for this, we can use this section element which you already have selected here,
so I do already select section here and store it in a constant in my app.js file, this is also available
here in this console as you can see if I type section here,
that's the section element and there, as on every element node, you have an innerHTML property.
You saw text content before which in the end gives you access to all text in there,
by the way that might be interesting, you see this is all the text of all the list items,
so not just direct child text but any nested text and you can also set new text content here, like this
which by the way will also replace any existing HTML content in there
if you now inspect this, so that's also interesting to see. Text content can also be used to set new
content but only text content, if you want to set new elements and so on, you use innerHTML and now
you can reset this equal to a string that contains HTML code, like for example a h2 tag, a new
title and important here is that this works as you can tell,
now we have this h2 element in there but it will always replace all the old HTML content, so any
previous nodes between the section tags and not just direct child nodes but any descendants will be entirely
replaced with this new HTML code.
So that's what innerHTML does, it really just swaps the entire nested HTML structure, all nested
nodes with your new content.
Sometimes that is exactly what you need and want, then this is great but sometimes you just want to add
a single new element and keep the old content and then innerHTML is not that great.
Now one workaround you might come up with is that you append content to innerHTML.
Let's say here we select the unordered list and store it in a list constant with query selector ul and
now I want to keep my existing list elements, so all existing three list elements and just add a new one.
Now you could do that by setting list innerHTML equal to and now list.innerHTML plus
and now a new content, right?
So now I add a string with a new list item here where I say item four.
This should in the end take the existing innerHTML content which is that structure we already
have here and just add a new list item at the end
that should be rendered. If we hit enter, this indeed works, the other three items are there and the new
one was added
but this approach has a major downside,
it becomes clear if we go to elements here and open my console here.
Now here I'll just repeat that code here just with item 5.
Now don't watch the console, also don't watch the part on the left, instead let's now watch this unordered
list here in this tree structure here in the elements tab
as I hit enter. Did you see that? It all flashed and this indicates that's how the chrome dev tools behave,
that all the items that flashed indeed changed and were kind of re-rendered.
So what happened here in the end is when we do that, we replace the entire HTML the content of the unordered
list with brand new content which yes is based on the old one but still everything gets re-rendered.
This has two important implications,
for one it's not great for performance.
You are forcing the browser to re-parse and re-render a lot of HTML which didn't change at all.
Now of course for a short list on a simple page like this one, it doesn't really matter
but if you're working with bigger web sites, bigger applications, that might be super bad and really hurt
the user experience.
Now in addition if you would do this to some other element, let's say this input and I can even show
this, then you'll face a totally different problem because let's say here in our index.html file, that
input would be inside of a div.
So I added a simple div, the only div I have on this page and I move my input in there.
So of course I can now get access to that div here if I reload by using document query selector div
and then let's say for some reason I want to change its content, so I reach out to innerHTML and
I set this equal to div.innerHTML plus let's say a paragraph which I want to add below it.
Something went wrong because the user entered something incorrect into the input let's say and you want
to tell the user,
right?
So we're rendering this paragraph and we're keeping all the original content,
we don't change this.
Now let's say I entered something here into the input, so I changed a text and now I execute this command.
Now what you'll see is that my input is lost
and the reason for that is that as I just explained, all the content which you swapped with innerHTML
is re-rendered, even if it's based on old content. A brand new element is rendered here and therefore
the user input is lost,
so that's the other downside of using that.
So innerHTML is useful whenever you want to change everything, all the HTML content of an element,
it's not so good
if you only want to add something to the existing content, that's one thing to keep in mind. Therefore
a better way of updating this, to keep the user input here which I just typed would be to use div insert
adjacent HTML,
this allows you to target a position and then define which HTML you want to enter. For that as so often,
it's good to Google for js insert adjacent HTML and find the respective MDN article and there
you find the different values for position where this should be inserted, before the element, just inside
before the first child, at the end of the element just after the last child or after the element itself
and here you also see a visual representation of where stuff is entered.
So we basically have four values - before begin, after begin, before end and after end
and hence here, we could say before end,
so inside of the element, inside of the div but after its last child,
so after the input in this case, I want to enter this paragraph,
something went wrong.
So now the same HTML code as before but inserted with insert adjacent HTML. The result is
if I now it enter,
this is kept and not reset,
instead we just added this new paragraph, in this case after the last paragraph which I entered with
this code here and now this does not re-render everything but really just insert this code and render
this new code
since you explicitly tell Javascript and the browser that this should be added next to the existing
content.
So this is one way of adding new content to an existing element with some HTML code which you write
in Javascript and this is therefore a great way of manipulating this.
Still whilst this might seem perfect, there are scenarios where you don't want to do it like this.