Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2: change DOM elements outside the root AppComponent

I have an observable -- loading$ -- that outputs true when I want to show a loading overlay in the UI, and false when it's time to remove that overlay. The visibility is controlled with a CSS class.

When the Observable emits true, I want to add the CSS class to the <body>, and remove it on false.

html

<body class="">
    <my-app>Angular app goes here</my-app>
</body>

As you can see, the <body> is outside of my Angular 2 app, so I cannot use property binding to change the class. This is what I currently do:

AppComponent.ts

loading$.subscribe(loading =>{
    if(loading) document.querySelector('body').classList.add('loading');
    else document.querySelector('body').classList.remove('loading');
});

This works well. The loading class is added/removed when the loading$ observable emits true/false. The problem is that I'd like to run my app in a web worker which means no access to the DOM. Plus, Angular recommends against manipulating the DOM directly.

How can I use Angular APIs to change <body>?

Angular 2, typescript 2, rxjs 5 beta 12

PS: This question looks promising, but the key link is dead. I've also seen a couple of suggestions that worked with Beta releases but are now obsolete (example)

like image 430
BeetleJuice Avatar asked Dec 22 '25 16:12

BeetleJuice


1 Answers

If you want an uninterrupted animation by DOM replacement in the middle of bootstrapping the app then use the following approach.

Put the overlay after my-app element.

<my-app></my-app>
<div id="overlay"></div>

Add @HostBinding to class.ready in main component app.component.ts:

@HostBinding('class.ready') ready: boolean = false;

Change the property when the data is loaded with the initial call (splash is still visible when your screen is not fully rendered).

constructor(private contextService: ContextService) {
    someService.initCall().then(r => this.ready = true);
}

Use CSS to hide the loader:

my-app.ready + .overlay {
    animation: hideOverlay 1s forwards;
}

@keyframes hideOverlay {
  0% {
        opacity: 1;
  }

  100% {
        opacity: 0;
        visibility: hidden;
  }
}
like image 165
kseb Avatar answered Dec 24 '25 10:12

kseb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!