Matthias Baumgart
Matthias Baumgart

Reputation: 965

How to style a sibling component in Angular2?

I have a search component containing a logo, a searchbar and a routeroutlet. The execution of a search navigates to the resultlist, which is the pseudo html outlined here:

<search>
  <logo></logo>
  <searchbar></searchbar>
  <result-list></result-list>
</search>

I like to style logo and searchbar differently on the results page so I tried to select the logo with :host >>> logo and the /deep/ alternative from the result-listcomponent. That doesn't work. Is there a way to select siblings?

Here a small plnkr to demonstrate the problem. http://plnkr.co/edit/Q0CLjcsftbqe0kHKrKks?p=preview Here I would like to style from resultlist the logo and the searchbarto be black.

Upvotes: 6

Views: 2009

Answers (3)

AngularTurk
AngularTurk

Reputation: 1

You can use services for communication between components and ngClass for dynamic styling.

notification.service.ts

import {Injectable, EventEmitter} from '@angular/core';

@Injectable()
export class NotificationService {
  private static _emitters: { [ID: string]: EventEmitter<any> } = {};

  static get(ID: string): EventEmitter<any> {
    if (!this._emitters[ID]) {
      this._emitters[ID] = new EventEmitter();
    }
    return this._emitters[ID];
  }
}

When sibling component run send a message.

bar.component.ts

import { NotificationService } from 'notification.service';
....
ngOnInit() {
      NotificationService.get('barcomponent').emit(true);
  }
  ngOnDestroy() {
      NotificationService.get('barcomponent').emit(false);
  }
...

Listen to incoming messages from your component.

foo.component.ts

import { NotificationService } from 'notification.service';
....
ngOnInit() {
    NotificationService.get('barcomponent').subscribe(value => {
        this.activateStyle = value;
    });
  }
....

You can apply any class via ngClass

foo.component.html

....
<div [ngClass]="{'my-css-class':activateStyle}">
  ...
</div>
....

Upvotes: 0

Matthias Baumgart
Matthias Baumgart

Reputation: 965

A Similar solution to the one from Jens Habegger using :host-context(myCssClass) and a conditional. The style needs to be added to the logo and the searchbar component.

<search>
  <logo [class.myCssClass]="isSearchResultList"></logo>
  <searchbar [class.myCssClass]="isSearchResultList"></searchbar>
  <result-list></result-list>
</search>
:host-context(.myCssClass) {
  color: black;
 }

Upvotes: 2

Jens Habegger
Jens Habegger

Reputation: 5456

What you are attempting is basically sharing global application state isSearchResultList: boolean across multiple components.

The obvious naive solution would be to hold the state at the respective shared parent component, and set it based on the current router-outlet.

<search>
  <logo [isSearchResultList]="isSearchResultList"></logo>
  <searchbar [isSearchResultList]="isSearchResultList"></searchbar>
  <result-list></result-list>
</search>

Upvotes: 1

Related Questions