Search code examples
angulartypescriptangular2-directivesangular2-components

Angular2 Toggle Class in child component using a click event in parent component


I am trying to toggle a class on/off using a click event, the problem I am running into is that my click event is in the parent component while the Class is in the child component. I am able to initialize the child with the class using @Input() decorator but I am unable to toggle the class afterwards

import { Component, AfterViewInit, Input, OnInit } from '@angular/core';
import { SidebarComponent } from './components/sidebar/sidebar.component';

@Component({
   moduleId: module.id,
   selector: 'body',
   host: {
      '[class.navMdClass]' : 'navMdClass',
      '[class]' : 'classNames'
   },
   templateUrl:'app.component.html' ,
   directives:[SidebarComponent],    
})
export class AppComponent implements OnInit {
   private isClassVisible:boolean;
   constructor () {    

   }
   ngOnInit() {
      this.isClassVisible=true;
   }
   toggleClass() {
      this.isClassVisible = !this.isClassVisible;       
   }
}
//Child component
import { Component, Input, EventEmitter, OnInit,SimpleChange } from '@angular/core';
@Component({
    moduleId: module.id,
    selector: 'sidebar',
    templateUrl:'sidebar.component.html' 
})

export class SidebarComponent implements OnInit{
    @Input() isClassVisible:boolean;

ngOnInit() { }
}
//Parent click event triggers toggleClass
<div class="nav toggle">
          <a (click)="toggleClass();" href="#" id="menu_toggle"><i class="fa fa-bars"></i></a>
      </div>
//Child div where target class is
<div class="left_col" [class.scroll-view]="[isClassVisible]" >

Solution

  • I found a solution to the problem this solution involves passing class names as properties to child component. If you have multiple classes to pass to different spots you can pass an array property and output in the proper areas.

    //parent component
    import { Component, AfterViewInit, Input, OnInit } from '@angular/core';
    import { SidebarComponent } from './components/sidebar/sidebar.component';
    
    @Component({
       moduleId: module.id,
       selector: 'body',
       host: {
          '[class.navMdClass]' : 'navMdClass',
          '[class]' : 'classNames[0]'
       },
       templateUrl:'app.component.html' ,
       directives:[SidebarComponent]
    
    
    })
    export class AppComponent{
    
       navMdClass:boolean;
       classNames:Array<any>;
    
       constructor () {
          this.navMdClass=false;
    
          this.classNames = ['nav-md', 'scroll-view',  'sidebar-footer'];
       }
    
       toggleClass() {
    
          this.navMdClass = !this.navMdClass;
          if(this.navMdClass==false){ this.classNames[0] = 'nav-md'; this.classNames[1]="scroll-view"; this.classNames[2]="sidebar-footer"}
          if(this.navMdClass==true){  this.classNames[0] = 'nav-sm'; this.classNames[1]=""; this.classNames[2]="sidebar-footer-hide"}
          //console.log(this.classNames[0]);
       }
    }
    //child component
    import { Component, Input, EventEmitter, OnInit, SimpleChange, OnChanges  } from '@angular/core';
    
    @Component({
        moduleId: module.id,
        selector: 'sidebar',
        templateUrl:'sidebar.component.html',
        properties: ['cls']
    })
    
    export class SidebarComponent{
        @Input() classNames:Array<any>;
    }
    
    //Parent click event triggers toggleClass
    <div class="nav toggle">
              <a (click)="toggleClass();" href="#" id="menu_toggle"><i class="fa fa-bars"></i></a>
          </div>
    //Sidebar selector in parent is where you pass the cls property declared in child component and pass it the classNames array from the parent component
    <sidebar [cls]="classNames"></sidebar>
    //Child div where target class is
    <div class="left_col {{cls[1]}}" >
    <div class="{{cls[2]}}" >