Search code examples
angularsassbootstrap-5angular12

Change class of ancestor from child component in Angular


I'm using the bootstrap container class in my app and because all but one page uses it, I stuck it in the app.component.html file:

<div class="container">
    <router-outlet></router-outlet>
</div>

I now have a single page though where I want to use container-fluid instead of container. Is there any way that the child component can change that class? I tried setting the margin in the child's scss the the !important tag but that didn't work. I also tried this to no avail:

::ng-deep :host-context(.container) {
  margin: 0 !important;
}

Answer

Updated to show the routing solution from Aviad P's comment. Just stick this in the app.component.ts file:

readonly #destroy$ = new Subject<void>()
fluid = false

constructor(private readonly router: Router) {
}

ngOnDestroy(): void {
    this.#destroy$.next()
    this.#destroy$.complete()
}

ngOnInit(): void {
    this.router.events.pipe(
        filter(x => x instanceof ActivationEnd),
        map(x => (x as ActivationEnd).snapshot.data),
        takeUntil(this.#destroy$)
    ).subscribe(x => {
        this.fluid = x.hasOwnProperty('fluid') ? !!x.fluid : false
    })
}

and in your HTML, you'd do this:

<div [ngClass]="{'container': !fluid, 'container-fluid': fluid}">
    <router-outlet></router-outlet>
</div>

Solution

  • Basically you need a service that will be the communication channel between the component of the route and the main component. That service will have a variable which will decide if the main component is container or container-fluid and each component can toggle it as they wish.

    container.service.ts

    @Injectable({ providedIn: 'root' })
    export class ContainerService {
      public fluid = false;
    }
    

    app.component.html

    <div [class.container]="!svcContainer.fluid" [class.container-fluid]="svcContainer.fluid">
        <router-outlet></router-outlet>
    </div>
    

    app.component.ts, 'page-one.component.ts`, ... - inject the service

      constructor(public svcContainer: ContainerService) {...}