Artful DI in Angular – Part 6: How to Modify the DOM Based on an Observable

So far in this series, we have almost finished our application that looks up data about grocery-store produce based on a PLU Code. In this post, we’ll install two niceties for the user experience. Both are based on setting the CSS class of an element based on the status of the lookup.

  • The PLU Code field should turn yellow while the lookup is underway, and then either green or red if the lookup succeeds or fails, respectively.
  • The image of the produce should show when and only when the lookup succeeds.

Here is a working version of the application so you can try it and see the effects. For example, if you enter a PLU Code of 3005 and then tab off that field, you will briefly see the field turn yellow, and then turn green once the data are retrieved.

To accomplish our two objectives, we will create a directive attribute, appLookupClass, that subscribes to the status Observable in the LookupService and sets a CSS class in its host element accordingly.

You saw the basic mechanism in Part 4, where we created a directive that listened for a browser event. The only difference is that now we’re subscribing to an RxJS Observable.

Recall from Part 3 that LookupService.status is a special kind of Observable called a BehaviorSubject, which can multicast to several subscribers. That lets us use the appLookupClass directive on more than one HTML element.

Without further ado, here is the code. A discussion follows.

In the @Directive decorator, the selector of '[appLookupClass]' tells Angular that when it encounters an attribute (the tip-off is the square brackets) named appLookupClass, it should plug in our code.

The constructor features the dependency injection that is by now familiar if you have read the other parts of this series, particularly Part 4.

It’s worth noting that the LookupService<any> that is injected is generic, which makes the directive suitable for any type of lookup, but when Angular encounters the directive in the context of the PluTrioComponent discussed in Part 5, it will inject the derived ProduceLookupService, which is what we want. See Part 5 for details.

The heart of this post, though, is the subscription that takes place in the constructor. That one line causes the updateClassForStatus method to be called every time the lookup status changes.

The updateClassForStatus method is fairly dull. It simply makes sure that the only the CSS class corresponding to the given status is on the host element.

By the way, the brutal way that’s done is not generally recommended. I removed all the status classes and then added the one we want. If you subtract and add the same class (for no net change), you suffer a performance hit with nothing to show for it. If there’s a lot of that on a page, you’ll notice it, as I have actually seen in one AngularJS application. However, I didn’t worry about it here for two reasons.

  • First, by the logic of this application, we will always get a new CSS class when that method is called. The status is never updated to the same thing.
  • Second, this method will not be called every time Angular is change-detecting. If this method were behind, say, an ngClass directive, that would be the case. However, this method will only be called when a status changes, and not during every change-detection cycle.

With that in place, we are set to accomplish the two objectives from the beginning of this post with just a little CSS.

First, we have the coloring of the PLU Code in the application’s styles.css. I put it there rather than in a component because, in my view, color choices belong at the application level (like a theme).

Second, the hiding of the image element when there is no image is easily done in the first three lines of plu-trio.component.css:

In the next and final post of this series, I will review what we have seen so far.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.