10

So the question is, is it possible to use the Renderer to tweak tags that are outside the main Angular 2 app component, like the tag? If yes, what is the best way to do this?

Let me give a bit of background. I'm trying to build a multilanguage site with Angular 2 and I came across a problem I could not find solution for. The thing is I am using the lang attribute in the html tag to define what language the site has at each moment, for example:

<html lang="en"> // When we have English locale active

So when the user clicks on a different language I update the site language using ng2-translate, which works perfect. The problem is that I need to update the property accordingly but I can't find the correct way of doing this in Angular 2 (if it's even possible). For now, I am directly touching the DOM but this won't work for me because I need to be abstracted from it (I'm using Universal too, so I need server side rendering to work).

For now, the styling of the app relays on this property (we support Arabic and this means changing the direction of the text if lang="ar"). I guess I could use a class on my main component or something like that, but using the lang property seems the correct approach to me. Any ideas?

Thanks

Markel Arizaga
  • 383
  • 1
  • 4
  • 13
  • Does this answer your question? [Angular - Update html attribute in root index.html](https://stackoverflow.com/questions/54203912/angular-update-html-attribute-in-root-index-html) – Luyang Du Jan 16 '20 at 15:39
  • Hey, thanks for the suggestion. I see the accepted answer in the linked question uses document directly and this is something I'm trying to avoid. Marking that answer as the correct one for this question as well could be misleading. I think the accepted answer in this question better reflects what I was looking for. – Markel Arizaga Jan 17 '20 at 17:02

1 Answers1

16

You can use the DOCUMENT DI Token from Angular to perform Dom operations:

import { Inject } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { DOCUMENT } from '@angular/common';

export class AppComponent {

    constructor(private translate: TranslateService, @Inject(DOCUMENT) private _document: any) {
        translate.onLangChange.map(x => x.lang)
            .subscribe(lang => this._document.documentElement.lang = lang);
    }
}
Ahmad Alfy
  • 13,107
  • 6
  • 65
  • 99
David Strahm
  • 263
  • 4
  • 10
  • Thanks fort he answer. I'm marking this as valid answer but I have another question based on your answer. Is this the recommended way of accessing the DOM outside the Angular app? I'm thinking on Angular Universal, which in case of being the recommended way it will have its own implementation of the DOCUMENT token eventually to enable server side usage. – Markel Arizaga Jun 09 '17 at 10:43
  • According to [Angular Universal Readme](https://github.com/angular/universal-starter#universal-gotchas) it should work on the server as long as you're not accessing native elements directly but I have not tried yet. You could always `import { isBrowser, isNode } from 'angular2-universal'` and don't run the parts that require the browser. This is also described in the documentation. – David Strahm Jun 14 '17 at 09:25
  • Yeah I used things like isBrowser but ideally I would like to avoid making a lot of if checks based on the environment because it will easily go out of control at some point. The thing is basically to have an implementation of DOCUMENT for the server side. If there is not one for now, I guess it's a matter of implementing one. Thanks again for the answers. – Markel Arizaga Jun 14 '17 at 14:28
  • 1
    Quick update, `DOCUMENT` now moved to `@angular/common`. – Ahmad Alfy Jul 26 '19 at 16:45