Yesterday, I took a quick look at trying to set the window / document title in an Angular 2 application. After I was done, however, something wasn't sitting right with me; all of the injectables in my demo specifically referenced the "browser" platform. A lot of work has been done, in Angular 2, to abstract the platform away so that it can be run a variety of different contexts. As such, I wanted to re-think setting the document title in a way that was platform agnostic.
Yesterday, I made reference to three browser-specific platform services when trying to set the document title:
Now, we want to get away from thinking about anything "browser" specific. But, we still need to be able to reference something outside of the root component (since Angular 2 can't be boostrapped on the entire HTML page). Luckily, the DOCUMENT token is also available in the common_dom export, which means its available across all DOM (Document Object Model) implementations. And, we already get a rendering engine in the Angular 2 core:
Together, we can use these two services to change the document title without making any references to the "browser" itself:
As you can see, we aren't even assuming that we know how to access the properties on the injected DOCUMENT. Instead, we are deferring to the Renderer to set the "title" property in case this is a non-trivial (or impossible) request in other rendering contexts. And, when we run this page, we can successfully set the document title:
Thinking in a platform-agnostic way is a huge mental leap when going from AngularJS 1.x to Angular 2. And, unfortunately, I don't see a lot of discussion about what that means from a practical sense for developers trying to execute on mundane tasks like setting the document title or cloning nodes (something I'm still experimenting with). But, at least now I have it in my mind to stay away from anything "browser" specific in the exported services in the Angular 2 framework.
Want to use code from this post? Check out the license.
Why not use this?
Good question. And, I'm not 100% convinced that my reasoning is correct. But, as I mentioned above, I did try to use that service - ng.platform.browser.Title - in my previous post:
... but, I wasn't super happy with the way it was clearly referencing the *Browser* platform. The moment that I make a hard reference to the Browser platform, it means that the browser DOM has to be implemented or mocked out in other environments (such as if I want to render the component on the server). As such, I wanted to see if I could use only *common DOM* platform stuff to set the title. By doing that, my hope is that it's up the selected platform to implement all of the "common" operations, which means that such an approach will be viable in any rendering context.
But, of course, there's not that much out there yet about how to think about multiple rendering contexts. So, it is completely possible that my thinking is either incorrect or not warranted.