It’s hard to write a webapp today without some sort of dynamic feed/list: Facebook’s news feed has photos, text statuses, ads, Twitter’s feed has promoted tweets, image tweets, retweets, and maybe you have a chat/messaging feed in your app with text, videos, photos and stickers.
While this is relatively common, it might not be straightforward to do so in Angular, or what is the Right Way™ for doing this.
Say that we get from a REST API a list of feed items, that look somewhat like this:
1 2 3 4 5 6 7 8 9 10
Naively, we might say what we really want is to create 2 directives, one for rendering text items (
text-feed-item) and one for images (
image-feed-item), and write something that looks like this:
Of course, this isn’t valid Angular code. So what should you do?
Keep it simple, stupid!
One of my main rules of thumb is to keep away from complexity as much as I can and be explicit. This means that if I have only a handful of different item directives to choose from, I’ll write something very explicit, like this:
1 2 3 4
This has the several advantages:
- Simple as can be
- Easily searchable (say, if you want to find who uses the
image-feed-itemdirective you can use plain search and find this)
But, in case you have more than a handful of different feed item types this might get out of hand or just plain get annoying.
Angular’s way of dynamically adding directives to the DOM is compiling them. I know the word “compile” feels quite odd in our little corner of web development, but for some reason that’s the word they chose for the process of having Angular parse a DOM node and executing all the Angular goodness it requires.
Making a dynamic directive that does basically what our first naive attempt looked like isn’t that hard, once you know about Angular’s
1 2 3 4 5 6 7 8 9 10 11 12
This will result in something that looks like this if you inspect the DOM:
1 2 3 4 5
As you can see,
$compile has two steps. First, we call it with the HTML we want to generate, which returns a function. We then call that function with the specific scope we want the generated element to have and then we actually get the new element that we can add to the DOM.
Yes, this is more complicated, requires being more comfortable with how Angular works and doesn’t have the benefits I listed above for the simpler solution, but sometimes this approach is necessary.