Reputation: 45
For each route in my application I need to change the parent background image. I'm using the style property in each nested component to achieve this, setting the ViewEncapsulation to None in each component so it will have a global effect. This works, but the problem is as I navigate through the app, I'm getting multiple instances of this style in the head tag:
<style>...</style>
<style>...</style>
Here is the code for the child component:
import {Component, Output, EventEmitter} from '@angular/core';
import {ViewEncapsulation} from '@angular/core';
@Component({
selector: '',
templateUrl:'app/home.component.html',
styles: [`
.hero-unit {
background:url('/app/assets/images/hero-01.png');
width:100%;
height:540px;
background-size: cover;
background-repeat: no-repeat;
background-position: 50% 50%;
}
`],
encapsulation: ViewEncapsulation.None
})
export class HomeComponent {
}
One overrides the other which is ok until you try to navigate back to a previous page, where the effect stops working. My question is, is there a way to remove a style property once I navigate away from that component and have it reinserted when I navigate back. Alternatively, is there a better way to swap out the background image based on route. I'm having a hard time finding the best method to achieve such a simple task in Angular 2. Thanks.
Upvotes: 0
Views: 2320
Reputation: 364727
You could use router data or a service.
Router solution
Put the image URL in the route data:
{ path: 'child1',
component: Child1Component,
data: { imageUrl: '/app/assets/images/hero-02.png' }
}
The parent component can then subscribe to route events, extract the URL and update the style property:
import {Component, Renderer, ElementRef} from '@angular/core';
import {Router, ActivatedRoute, NavigationEnd} from '@angular/router';
@Component({
template: `<section>
UserComponent content here, if any.
<nav>
<a [routerLink]="['./']">Activity</a>
<a [routerLink]="['profile']">Profile</a>
- child routes
</nav>
<div class="child-view">
<router-outlet></router-outlet>
</div>
<section>`
})
export class UserComponent {
constructor(private router: Router, private route: ActivatedRoute,
private renderer:Renderer, private elref:ElementRef) {}
ngOnInit() {
this.router.events
.filter(event => event instanceof NavigationEnd)
.subscribe(_ => {
let childRouteSnapshot = this.route.firstChild.snapshot;
let url = childRouteSnapshot.data.imageUrl;
this.renderer.setElementStyle(this.elref.nativeElement.childNodes[0],
'background-image', 'url(' + url + ')');
})
}
}
Here's a working Plunker. (Note that some of the code in the plunker is only half way converted to RC5. The code shown above is all RC5.)
I had to use childNodes[0]
because in my example elref
was set to ng-component
rather than the <section>
.
Service solution
Use a shared service. See Cookbook section Parent and children communicate via a service. Children components publish events (i.e., URL image strings) on an observable/subject that the parent component subscribes to.
Upvotes: 2