Learning Angular - Directives: ngStyle
I am continuing my journey in the Angular framework and figuring out how to work with CSS styles better given what I have learned already.
I will show/hide items using CSS style attribute visibility
based on
a value in the component.
Angular has certain tools designed to work with CSS styles.
This article will take you five minutes to read.
Introduction
I want to extend my knowledge of Property Bindings and use them to show/hide items, like a picture of a dog!
Let’s follow the same format as before, processing an input field, if the input field has the matching value, show a picture of a dog, otherwise, show nothing.
To show/hide, I will use the CSS Style: visibility
and use what I
know display:
Following Along
If you would like to follow along with this code, you can use the Github link to get a final copy of the code or view the project in your browser using this StackBlitz link.
Basic CSS
Let’s make sure I know I have the syntax working properly for
visibility
and solve the problem with just CSS:
Showing an image:
<img style="visibility: visible"
src="https://www.dropbox.com/s/ugeqlxvawfqwhth/dog_by_roaming_angel.jpeg?raw=1">
The result:
To hide the image:
<img style="visibility: hidden"
src="https://www.dropbox.com/s/ugeqlxvawfqwhth/dog_by_roaming_angel.jpeg?raw=1">
The result:
Changing visibility
from Component?
How can we convert this to be more dynamic, to have the component
control visibility
value?
Let’s use the first technique, string interpolation:
<img style="visibility: {\{ showDog }\}"
src="https://www.dropbox.com/s/ugeqlxvawfqwhth/dog_by_roaming_angel.jpeg?raw=1">
Where showDog
is in the component:
export class AppComponent {
showDog = 'visible';
}
Let’s try that and see the result:
Oh - it shows. Cool, let’s set showDog
to hidden
and see the result:
Huh? This should be “hidden”, why is this showing up?
Looking at the inspector for this section, this is the HTML:
<img _ngcontent-lgq-c0="" src="https://www.dropbox.com/s/ugeqlxvawfqwhth/dog_by_roaming_angel.jpeg?raw=1" style="">
The fact style=""
means the string interpolation does not work
here. Changing showDog
will not change the image visibility.
Property Bindings to the rescue?
Let’s use what we learned from the last article: Property Bindings!
<img [visibility]="showDog"
src="https://www.dropbox.com/s/ugeqlxvawfqwhth/dog_by_roaming_angel.jpeg?raw=1">
The result:
Hmmm - there’s nothing displayed, this is not good. Time to check the console:
Uncaught Error: Template parse errors:
Can't bind to 'visibility' since it isn't a known property of 'p'. ("
</p>
Ooooh - that’s weird. This approach worked for disabled
, why not
for visibility
?
Let’s try one more thing: bind to the property style
, because
style
sets visibility
:
<img [style]="visibility: showDog"
src="https://www.dropbox.com/s/ugeqlxvawfqwhth/dog_by_roaming_angel.jpeg?raw=1">
Nope, nothing here either. What does the console error have this time?
Uncaught Error: Quotes are not supported for evaluation!
Statement: showDog located at ng:///AppModule/AppComponent.html@0:14
at _AstToIrVisitor.visitQuote (compiler.js:7646)
Hmmm - something tells me my approach is wrong here.
Difference
visibility
is an attribute on a CSS style, to use it,visibility
attribute is part ofstyle=
method. It’s defined as a CSS property - (so why can’t property bindings work?! :-) )disabled
is an CSS pseudo-class where it is an attribute on the element and style.
Web development is confusing!
Back to Documentation
Well, terminology doesn’t line up, let’s go back to Angular’s documentation to see if there’s a hint.
Searching in the documentation for “style”, as we want to see what tools are there to manage CSS styles:
An attribute directive that updates styles for the containing HTML
element. Sets one or more style properties, specified as
colon-separated key-value pairs. The key is a style name, with an
optional .<unit> suffix (such as 'top.px', 'font-style.em'). The value
is an expression to be evaluated. The resulting non-null value,
expressed in the given unit, is assigned to the given style
property. If the result of evaluation is null, the corresponding style
is removed.
💡‼️
Let’s try using this straight up with showDog=hidden
:
<img [ngStyle]="{ visibility: showDog }"
src="https://www.dropbox.com/s/ugeqlxvawfqwhth/dog_by_roaming_angel.jpeg?raw=1">
And the result with showDog=hidden
:
Setting showDog=visible
result:
Cool. Hidden hides the image, visible displays the image. Exactly what we want.
NgStyle
controls CSS styles. The last approach of setting style
was on the right track!
Styles, styles, styles!
When there are more styles, say: colors, background colors, etc.
<img [ngStyle]="{ visibility: showDog, background-color: backgroundColor, font-size: fontSize, font: font }"
src="https://www.dropbox.com/s/ugeqlxvawfqwhth/dog_by_roaming_angel.jpeg?raw=1">
Can get a bit tedious setting it inside the template. The component
class can set all of the styles at once using NgStyle
.
export class AppComponent {
visibility = 'visible';
backgroundColor = 'blue';
dogStyle = {
'visibility': this.visibility,
'background-color': this.backgroundColor
}
}
To me, this is a win as the component is manipulating all styles instead of writing it out in the element, layering in functionality.
Conclusion
Trying to use Angular’s string interpolation {\{}\}
methods for
styles might have worked, if I always wanted something to be
visible
.
Using property binding was worse, nothing displayed on screen when
using it as is on the visibility
property. Using property binding
with style
is on the right track, no success.
The ngStyle
directive is a better designed solution for manipulating
styles than manually working with the template. One can manipulate
them however they want in code, a real win in managing complexity.