Search code examples
angularcssflexboxangular-router

Generalized solution for applying flex rules to multiple Angular 4 components


I have multiple tabs and sub-tabs in my application and each of those tabs and subtabs is a component. They need to grow and shrink as available space to them grows or shrinks.

One key step to achieve that flexible layout is setting following main CSS rule in my app level CSS file for all of the components which are children of the main app:

/* app-level.component.css */
:host ::ng-deep tab1,
:host ::ng-deep tab2,
:host ::ng-deep tab1-subtab1,
:host ::ng-deep tab1-subtab2 {
{
  display: flex;
  flex: 1 1 auto;
  flex-flow: column nowrap;
}

where tab1, tab2, tab1-subtab1, tab1-subtab2 are selectors e.g. for tab1:

/* tab1.component.ts */
@Component({
  selector: 'tab1',
  templateUrl: './tab1.component.html',
  styleUrls: ['./tab1.component.css']
})

Above mentioned in just an example. Consider an application with 10 tabs and many subtabs. In that case, first problem is that I will have to manually write down selectors for all those tabs in the app-level.component.css.

Another problem is that in near future some new developer may introduce a new tab but his tab's content will not grow-shrink as expected because he/she doesn't even know that they have to add their component's selector to the app-level-component.css.

Is there a more generalized and recommended way to approach this problem with Angular 4 such that:

  1. I don't have to pollute app.component.css with all those selectors
  2. Each future tab automatically have the style applied to it already.

I suppose Decorators may be the right way to go about this in order to at-least solve #1. For #2, it seems like the developer of new tab will have to at-least apply that decorator to his component so there is some work he/she will have to do but its not as bad as figuring out addition of the required rule to app-component.css. Which kind of decorator should I look into?

Note: tab1, tab2, tab1-subtab1, tab1-subtab2 are not classes. They are components generated by Angular Router.


Solution

  • Two main constraints were mentioned in the answer's description:

    1. app.component.css should not be polluted with selectors for each component
    2. Each future tab automatically have the style applied to it already.

    Following app level generalized CSS rule takes care of both. As those components were generated by Angular Router. We find router-outlet and apply the CSS to its immediate sibling (by using the adjacent sibling combinator) which are our components for tabs and subtabs.

    :host ::ng-deep router-outlet + * { 
       display: flex; 
       flex: 1 1 auto; 
       flex-flow: column nowrap 
    } 
    

    New developers will not have to do anything extra for their new tabs/subtabs.