Angular 2: Changing DOM inside head tag

Last few weeks, I’ve been working with the beta versions of Angular 2. Some history: I started in december 2015 with Angular 1 and it took some time to learn. However, I liked the framework and posibilities. I also went this year to NG-NL, an Angular conference in the Netherlands. The Angular team announced that a stable version of Angular 2 will be released this year (2016). Angular 2 is a huge difference compared to Angular 1, because the Angular team started the framework from scratch. In my opinion, the framework is much easier to learn and also much easier to understand. However, that are opinions :). Secondly, my company decided to use Angular 2 for one of their applications so I decided to dive a bit more into Angular 2.

There are a lot of differences between AngularJS and Angular 2. For this example, the biggest impact is the bootstrap position of both frameworks. In AngularJS, ng-app is defined in the html tag, which is also the bootstrap position. This means that you can acces the whole DOM within the AngularJS framework. Angular 2 apps bootstrap position is in the body tag. So basically, you cannot acces directly the head and body tag using Angular 2.

And this is problematic for this use case. In this use case, we want to give my website themes (different colors based on company/user). In technical terms, we need to change/swap stylesheets in the DOM. To accomplish this we need to manipulate elements in the head tag.

First some information: How to change a stylesheets in the DOM itself? If you want to provide style sheets for your site, you need to give each style sheet a title, so we are able to identify stylesheets. Next, we can tell the browser which stylesheet is active. We can do that by annotating the link tag with the attribute ‘disabled’. An example is shown below:

<html>
   <head>
       <link rel="stylesheet" type="text/css" href="style/blue.css" title="blue">
       <link rel="stylesheet" type="text/css" href="style/red.css" title="red" disabled>
    </head>
    <body>Here some content...</body>
</html>

style/red.css

body {
   color: red;
}

style/blue.css

body {
    color:blue;
}

In the example above i have 2 stylesheets, titled red and blue. The stylesheet is only coloring the body tag to a specific color. In this case, the blue stylesheet is active and the red one is disabled (annotated the red stylesheet with the attribute ‘disabled’.

Now we know how to change stylesheets in the DOM, we want to control this in our Angular 2 application. At this moment, Angular 2 does not have ‘out-of-the-box’ functionality to change the DOM in the head tag. Because we use typescript in our Angular 2 example, we can also use plain javascript properties and functions. Using plain javascript, we can modify everything in the DOM. See the example below:

import {Component, OnInit} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: 'Current color: {{style}} <br/><button (click)="onChange()">Change style</button>'
})
export class AppComponent implements OnInit { 
  
  private style: string;
  
  ngOnInit() {
    //Default
    this.changeStyle('Red');
  }
  
  onChange() {
    if(this.style === 'Red')
      this.changeStyle('Blue');
    else
      this.changeStyle('Red');
  }
  
  changeStyle(style) {
    this.style = style;
    
    //Change value of the meta tag
    var links = document.getElementsByTagName("link");
    for(var i=0; i < links.lenght; i++) {
        var link = links[i];
        if(link.getAttribute("rel").indexOf("style") != -1 && link.getAttribute("title")) {
              link.disabled = true;
              if(a.getAttribute("title") === this.style)
                 link.disabled = false; 
        }
    }
  }
}

This component contains a button and some text which style is activated. When the button is clicked, the changeStyle function is called. This function travers through all stylesheets with a title. First, it disables the stylesheet en enables the stylesheet when the title name is equals to the title given as parameter. The basic idea behind this principle is to give stylesheet a title per category (e.g. blue/red) and don't use titles for global stylesheets.

And that's it! Easier then expected. When you run the above component, you get the result below. Pressing the button changes the active style.

Result Changing stylesheet

Note that Angular 2 is still in beta, so syntax might change in the future! or maybe Angular 2 will provide some standard functionality for this use case. Time will learn :).

Leave a Reply

Your email address will not be published. Required fields are marked *