While this theoretically works, there's a significant problem with it. Let's take a look at what the HTML looks like when rendering with onlyShowFiles=true and the following filesArray:
Any search engines reading data off of your page may incorrectly assume that your list is intentionally empty, thus potentially impacting your ranking on sites.
Solving these issues is where something called "transparent elements" comes into play. See, ideally, what we want to have is something like a tag that renders to nothing.
This means that if we could instead generate something like the following pseudo-syntax in framework code:
Fragment also has an alternative syntax in JSX. Instead of <Fragment></Fragment>, you can simply do <></>. This shorthand removes the need for the import and makes the above code sample read like this:
You may notice that <> syntax for Fragment does not have a key associated with it. This is because the <> syntax does not allow you to have props associated with it.
However, this means that your loop will still misbehave and add performance overhead as a penalty for not including key (as we discussed in the "Dynamic HTML" chapter). For this reason, when inside a map loop, you'll want to use Fragment with a key property associated with it.
Angular's version of the nothing element is the ng-container element.
However, unlike React and Vue; we don't need to use ng-container in this example. Angular allows us to have multiple elements at the root of any control flow block, so we can remove the ng-container and have the following:
This has the same effect as the previous example, but with less code. We'll continue to use ng-container in this chapter to keep the examples consistent with other frameworks, but there's little need for it in most modern Angular codebases.
To render out something akin to a nothing element, we can use a template element with a v-for or v-if associated with it.
While the other frameworks have a more 1:1 mapping between our pseudo-syntax nothing, Vue has a slightly different approach due to its reuse of the existing HTML <template> tag.
By default, if you render a template in Vue in any other place besides the root, it will render nothing to the screen:
It's worth mentioning that even if it shows nothing on screen, the template element is still in the DOM itself, waiting to be used in other ways. While explaining "why" an HTML template element renders nothing by default is outside the scope of this book, it is expected behavior.
However, if you add a v-for, v-if, or a v-slot (we'll touch on what a v-slot is in our "Accessing Children" chapter), it will remove the <template> and only render out the children.
Of course, these rules don't apply to the root-level template, that acts as a container for our template code. It's a bit confusing at first, but makes sense when you practice more.
Challenge
Now that we understand how to render a transparent element (transparent to the DOM, anyway), let's build out an example where this would be useful.
Namely, let's assume that we want to build out a bar of buttons with a gap between them:
To do this with HTML, we might have the following template and styling:
That's because when we used a div for our FileActionButtons component, it bypassed the gap property of CSS. To fix this, we can use our handy dandy nothing element:
This causes our gap root to not apply to the inner buttons. To sidestep this, we need to use styles and tell our host component to treat the buttons container as if it doesn't exist.
Final code output
An embedded webpage:Angular Dynamic Challenge - StackBlitz