You Can Render Anything In Angular
source link: https://www.bennadel.com/blog/4357-you-can-render-anything-in-angular.htm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
You Can Render Anything In Angular
The other day, I heard someone say something to the effect of: In an Angular application you're stuck doing it "The Angular Way". The person saying this was implying that it's somehow easier to perform low-level programming in React. If anything, I'd argue that the opposite is more true; however, I don't wish to compare Angular to React - I just want to flesh-out what might be a missing mental for some developers. In case you didn't know, in Angular, you can render anything you want. Breaking out of the Angular application life-cycle and performing custom work is relatively straightforward.
Run this demo in my JavaScript Demos project on GitHub.
View this code in my JavaScript Demos project on GitHub.
To explore this idea, consider the following TypeScript class, Messenger
. It accepts a DOM (Document Object Model) element and exposes a renderMessage()
method. This class does not know anything about Angular at all. It doesn't know anything about any framework that might be consuming it. It doesn't import any classes or apply any directives or decorators. It's just vanilla TypeScript / JavaScript that performs its own DOM manipulations:
Now, this JavaScript class won't magically instantiate itself - we have to create something in Angular world that invokes the Messenger
constructor and passes in a DOM element on which the Messenger
class can act. To do this, I'm going to create a light-weight wrapper component that acts as the liaison between the Angular life-cycle and the Messenger
life-cycle.
This wrapper / liaison component does two main things:
-
It makes sure to instantiate the
Messenger
class outside of the Angular Zone. Angular simplifies state management / DOM reconciliation by monkey-patching a number of low-level DOM methods (ex,setTimeout()
andaddEventListener()
). This way, Angular knows to trigger a change-detection life-cycle when low-level actions take place inside the application.In our case, however, since we intend to render something wholly custom within our Angular application, we don't want the monkey-patched methods to be used by our
Messenger
class. As such, when we instantiate theMessenger
class, we're going to do it via Zone'srunOutsideAngular()
method. This way,Messenger
can only access the original, native DOM methods. -
It pipes any necessary view-model changes into the
Messenger
instance. In our case, that means calling the.renderMessage()
method whenever the relevantname
value changes. In our demo, that's going to be done via a simpleNgModel
two-way data-bindings.
The following light-weight wrapper component exposes an Input
, name
. We then use the ngOnChanges()
life-cycle method to make sure that new value gets pumped into the Messenger
instance via renderMessage()
:
As you can see, this wrapper component is acting as an extremely light-weight conduit between the Angular application and the underlying Messenger
class.
To see this light-weight wrapper in action, let's use it in our App component. Notice that we're using [(ngModel)]
two-way data bindings to seamlessly and effortlessly pipe view-model changes into our wrapper:
And, when we run this Angular 15 code, we get the following output:
As you can see, our updated name
value in Angular's view-model is pushed down into the Messenger
instance via the ngOnChanges()
life-cycle method. And, the mouseenter
and mouseleave
events - bound inside the Messenger
class - have no problem updating the DOM.
If you step back for a minute and think about what "Angular" is at a high-level, it's really just a way to take state (your Classes) and reconcile that state with the DOM (your templates). To render something "completely custom" inside an Angular application, all you're really doing is using a "template" to render the "custom thing". And then, optionally, hooking into the state reconciliation life-cycle in order to push changes down into that template.
If anything, Angular's stateful component approach more closely mirrors the browser's native stateful DOM approach (when compared to some other frameworks). This should make it easier to build completely custom things in Angular - not harder.
Hopefully this helps clear up any confusion or misconceptions that newer developers might have about the Angular web application framework.
Want to use code from this post? Check out the license.
Enjoyed This Post? ❤️ Share the Love With Your Friends! ❤️
Reader Comments
interesting read. i have worked with angular and react, and react also provides a similar escape hatch. my guess is all of frameworks allow an escape hatch like this.
@Hassam,
I've only played with earlier versions of React that had life-cycle methods (like componentWillMount()
and stuff). In that case, it feels like a relatively similar approach. When it comes to "new" React with Hooks, I don't know how it would work. I feel like you'd have to create a special Effects hook or something that depends on the prop ... I'm talking out of my depth though.
Post A Comment — ❤️ I'd Love To Hear From You! ❤️
Name:
Email:
Website:
Subscribe to comments.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK