When building Angular components, have
you ever found yourself looking for a way to provide fallback content for projected
content slots using the ng-content element? If so, you’ve probably been able to
find some work arounds to do it but, they’re probably not something
you really want to do. It would be better if this concept
was built-in to the framework, right? Well, this is actually happening
in the latest versions of angular. In this video I’ll show you exactly how it works. Alright, let’s get to it. Ok, a little disclaimer before
we get into this example, what you’ll see here in this video will
require Angular version 18 or above. If you’re on an earlier version, unfortunately, you’ll need to upgrade before you can
use the techniques from this video. Ok, we’re going to start with a demo
application that we built for another example where we converted static string inputs over to attributes with the inject()
function and the HostAttributeToken. If you haven’t watched that video
yet, you should check it out next! For this example, we have an application
built for the Vans clothing brand. We’re going to be working
with these two buttons here. We can see that the first
button has two text regions, the first reads “Shop Now!”, and the
second reads “Browse all Clothing”. Then we have the labels on the second button
that read “Sign Up”, and “And Save Today”. These two buttons use an
existing button component. If we look at the code for this
button, we can see that we have a “primaryLabel” attribute and an
optional “secondaryLabel” attribute. Now if we look at the template, here we
can see we have a strong element that contains the string interpolated
value of the “primaryLabel”. And then, if we have a “secondaryLabel”, we output the string interpolated
value of it within an em tag. Ok, so now that we know how it’s working,
let’s take a look at the template for the page-content component where the
usages of these two buttons exist. Here is the code for the first button
with its labels, and here is the second. So that’s how these buttons
are currently configured, but in this video, we’re going to
change this around a little bit. We’re going to change these labels over to
content slots with the ng-content element, and then we’re going to set those slots up to have fallback content when we don’t
provide content to the slots. Ok, so let’s start by converting
these labels over to slots. To do this, we need to start within
the button component template. Let’s add an ng-content element. Now on this element, we’re
going to add a select attribute. And we’ll select the strong element. So, this will now take a strong element contained within the open and close tags for the
button component and project it here. Now we’ll do the same with the “secondaryLabel”
only this time we’ll select an em tag instead. Next, let’s remove the attributes from the code for this component since
we’re not using them anymore. Now, we need to update the usages of these
buttons in the page-content component. For the first button, let’s move the “primaryLabel” string
to a strong element within the button. And, let’s move the “secondaryLabel”
string to an em tag within the button. And now let’s do the same for the second button. There, now let’s save and see how this looks. Nice, nothing changed so it
looks like we got it right. Kinda boring so far though right? But here’s where the cool part comes in. Let’s say that we use this button
in several places and most of the time we want it to have the text from first
button, “Shop Now”, and “Browse All Clothing”. Then, sparingly, we will want
to do what we’re doing on the second button where we provide unique labels. This is now really easy to do. Let’s just go into the template
for the button component. Then, within the first slot, let’s add a
strong element with the text “Shop Now!”. We can simply provide the fallback content
that we want right in the slot now. Let’s add and em tag in the second slot
with the text “Browse all Clothing”. That’s it. Now, if we don’t include a strong element or an
em tag, it will show what we’ve include here. Now all that’s left is for us to go and update the usage for the first button
in the page-content component. We can just remove the strong and
em tags from within the button. Ok, now let’s save and make
sure it’s working like we want. Perfect. It’s all working great. Now there is one thing to be
aware of with this method. If the content provided to
the slot is conditional, the fallback content will
actually not be displayed. To illustrate this, if we take a look at the
code for the page-content component, you can see that I’ve now added a “showSignUpLabel”
signal with an initial value of false. Let’s switch over to the template and
make the label content conditional based on the current value of this
signal using an if statement. Then, just for demonstration purposes,
let’s toggle this value on click. Now, let’s save and see what happens. There, now you can see, since
this value was false when the component was created, we have no value initally. Since we’re now dynamically adding the
slot, we no longer get the fallback content. And if we click to toggle the value,
then we see the “Sign Up” label. And when we toggle it again, it goes away. So, just keep in mind that the fallback content
will not work with dynamic slot content. So that’s all pretty cool right? We now have a native way to provide fallback content to projected content slots
using the ng-content element. No more crazy conditional logic is
needed to do this type of thing. Ok, that’s all for now. Until next time, thanks for watching.