Issue
Currently I have an app component that has a sidenav and my router-outlet
in the sidenav content. In this component I manage the app theme by adding or removing the darkMode
class in my style.scss
.
Is there a way to control what background-image I’m using?
What if I also wanted to control the background image based on what component is opened on the router-outlet
? Would that be possible to? Maybe not setting the background-image in the app component but on the opened component instead
app.component.html
<mat-sidenav-container autosize class="h-100">
<mat-sidenav #sidenav mode="side" opened="true">
<mat-nav-list>
<mat-list-item>
<mat-slide-toggle [formControl]="toggleControl"></mat-slide-toggle>
</mat-list-item>
...
<mat-sidenav-content>
<router-outlet></router-outlet>
</mat-sidenav-content>
app.component.ts
@HostBinding('class') className = '';
toggleControl = new FormControl(false);
constructor(private overlay: OverlayContainer, ...) { }
ngOnInit() {
this.toggleControl.valueChanges.subscribe((darkMode) => {
const darkClassName = 'darkMode';
this.className = darkMode ? darkClassName : '';
if (darkMode) {
this.overlay.getContainerElement().classList.add(darkClassName);
} else {
this.overlay.getContainerElement().classList.remove(darkClassName);
}
});
this.subscription = this._service.currentLogStatus.subscribe(logStatus => this.loggedIn = logStatus);
}
app.component.scss
mat-sidenav-container {
background-image: url('../assets/img/home-background.png');
}
style.scss
.darkMode {
@include mat.all-component-colors($angular-dark-theme);
}
Update
After some indications I’ve tried.
The darkMode
background still presists on the ProfileComponent, even though I have another background referenced.
app.component.html
<mat-sidenav-content>
<router-outlet (activate)="onRouterOutletActivate($event)"></router-outlet>
</mat-sidenav-content>
app.component.ts
ngOnInit() {
this.toggleControl.valueChanges.subscribe((toggled) => {
console.log(this.currentComponent);
this.className = toggled ? 'darkMode' : '';
if (toggled) {
if (this.currentComponent == "home") {
this._overlay.getContainerElement().classList.add('darkMode');
this._overlay.getContainerElement().classList.remove('darkModeProfile');
}
if (this.currentComponent == "profile") {
this._overlay.getContainerElement().classList.add('darkModeProfile');
this._overlay.getContainerElement().classList.remove('darkMode');
}
} else {
if (this.currentComponent == "home") {
this._overlay.getContainerElement().classList.remove('darkMode');
}
if (this.currentComponent == "profile") {
this._overlay.getContainerElement().classList.remove('darkModeProfile');
}
}
});
this.subscription = this._service.currentLogStatus.subscribe(logStatus => this.loggedIn = logStatus);
}
public onRouterOutletActivate(event : any) {
if (event.constructor.name == "ProfileComponent") {
this.currentComponent = "profile";
}
if (event.constructor.name == "HomeComponent") {
this.currentComponent = "home";
}
}
app.component.scss
mat-sidenav-container {
background-image: url('../assets/img/home-background.png');
}
:host-context(.darkMode) {
mat-sidenav-container {
background-image: url('../assets/img/home-background-dark.png');
}
}
:host-context(.darkModeProfile) {
mat-sidenav-container {
background-image: url('../assets/img/profile-background.png');
}
}
Solution
The solution that worked for me was to maintain the .darkMode
class and use different backgrounds based on what component is being rendered by router-outlet
Solution
app.component.html
<mat-sidenav-container [ngStyle]="{ 'background':
'linear-gradient( rgba(0, 0, 0,' + theme + '), rgba(0, 0, 0,' + theme + ')),'+
'url(../assets/img/' + currentComponent + '-background' + '.png)'}"
autosize class="h-100">
<mat-sidenav #sidenav mode="side" opened="true">
<mat-nav-list>
<mat-list-item>
<mat-slide-toggle [formControl]="toggleControl"></mat-slide-toggle>
</mat-list-item>
...
<mat-sidenav-content>
<router-outlet (activate)="onRouterOutletActivate($event)"></router-outlet>
</mat-sidenav-content>
</mat-sidenav>
</mat-sidenav-container>
app.component.ts
currentComponent: string = "home";
theme: number = 0;
constructor(private _overlay: OverlayContainer) { }
ngOnInit() {
this.toggleControl.valueChanges.subscribe((toggled) => {
this.className = toggled ? 'darkMode' : '';
if (toggled) {
this._overlay.getContainerElement().classList.add('darkMode');
this.theme = 0.5;
} else {
this._overlay.getContainerElement().classList.remove('darkMode');
this.theme = 0;
}
});
this.subscription = this._service.currentLogStatus.subscribe(logStatus => this.loggedIn = logStatus);
}
public onRouterOutletActivate(event : any) {
if (event.constructor.name == "ProfileComponent" || event.constructor.name == "RegisterComponent") {
this.currentComponent = "profile";
}
if (event.constructor.name == "HomeComponent") {
this.currentComponent = "home";
}
}
style.scss
.darkMode {
@include mat.all-component-colors($angular-dark-theme);
}
Doing it this way, I can control what image is shown and apply a filter when the .darkMode
is enabled.
Answered By – André Clérigo
Answer Checked By – Katrina (AngularFixing Volunteer)