73

In Angular, I would like to use ngClass and click event to toggle class. I looked through online but some are angular1 and there isn't any clear instruction or example. Any help will be much appreciated!

In HTML, I have the following:

<div class="my_class" (click)="clickEvent($event)" ngClass="{'active': toggle}">
  Some content
</div>

In .ts:

clickEvent(event) {
  // Haven't really got far
  var targetEle = event.srcElement.attributes.class;
}
Steve Kim
  • 4,856
  • 11
  • 46
  • 90

9 Answers9

146

This should work for you.

In .html:

<div class="my_class" (click)="clickEvent()"  
    [ngClass]="status ? 'success' : 'danger'">                
     Some content
</div>

In .ts:

status: boolean = false;
clickEvent(){
    this.status = !this.status;       
}
Alexandre Aimbiré
  • 1,188
  • 11
  • 24
Mani S
  • 2,331
  • 1
  • 11
  • 12
  • Just a quick question. The first click adds the class just fine, but the second click doesn't seem to work. From your code, I don't see how it changes the `status` back to `false`. – Steve Kim Jun 14 '17 at 05:01
  • 3
    made changes to my code., you can set it to false initially and then the function will toggle the bool value to true false. – Mani S Jun 14 '17 at 05:24
72

Instead of having to create a function in the ts file you can toggle a variable from the template itself. You can then use the variable to apply a specific class to the element. Like so-

component.html -

<div (click)="status=!status"  
    [ngClass]="status ? 'success' : 'danger'">                
    Some content
</div>

So when status is true the class success is applied. When it is false danger class is applied.

This will work without any additional code in the ts file.
EDIT: Recent versions of angular require the variable to be declared in the controller - component.ts -

status: boolean = false;
charsi
  • 2,406
  • 18
  • 39
  • 2
    Would you have to declare "status" in the template? – webworm Jan 07 '19 at 17:01
  • @webworm no, you do not need to declare `status` in the template. – ANeves Mar 25 '19 at 22:58
  • 2
    Is it possible to use this approach also for a div inside an ngFor ? Because I try it, but it seems that angular change the class to all the div created with ngFor, not only to the one that I click; thanks. – S-Wing Dec 03 '19 at 10:02
  • Getting error that the - Property 'status' does not exist on type – sin2akshay Nov 16 '21 at 12:02
  • @sin2akshay looks like things have changed in angular recently so you'll have to declare the variable first. I've updated the answer above. – charsi Nov 17 '21 at 08:41
38

Angular6 using the renderer2 without any variables and a clean template:

template:

<div (click)="toggleClass($event,'testClass')"></div>

in ts:

toggleClass(event: any, className: string) {
  const hasClass = event.target.classList.contains(className);

  if(hasClass) {
    this.renderer.removeClass(event.target, className);
  } else {
    this.renderer.addClass(event.target, className);
  }
}

One could put this in a directive too ;)

neox5
  • 1,401
  • 11
  • 15
13

ngClass should be wrapped in square brackets as this is a property binding. Try this:

<div class="my_class" (click)="clickEvent($event)"  [ngClass]="{'active': toggle}">                
     Some content
</div>

In your component:

     //define the toogle property
     private toggle : boolean = false;

    //define your method
    clickEvent(event){
       //if you just want to toggle the class; change toggle variable.
       this.toggle = !this.toggle;       
    }

Hope that helps.

mentallurg
  • 4,570
  • 5
  • 25
  • 34
Saurabh Tiwari
  • 4,002
  • 8
  • 36
  • 69
8

If you're looking for an HTML only way of doing this in angular...

<div #myDiv class="my_class" (click)="myDiv.classList.toggle('active')">
  Some content
</div>

The important bit is the #myDiv part.

It's a HTML Node reference, so you can use that variable as if it was assigned to document.querySelector('.my_class')

NOTE: this variable is scope specific, so you can use it in *ngFor statements

Craig Wayne
  • 3,881
  • 3
  • 34
  • 45
2

We can also use ngClass to assign multiple CSS classes based on multiple conditions as below:

<div
  [ngClass]="{
  'class-name': trueCondition,
  'other-class': !trueCondition
}"
></div>
MiPhyo
  • 39
  • 5
1

If you want to toggle text with a toggle button.

HTMLfile which is using bootstrap:

<input class="btn" (click)="muteStream()"  type="button"
          [ngClass]="status ? 'btn-success' : 'btn-danger'" 
          [value]="status ? 'unmute' : 'mute'"/>

TS file:

muteStream() {
   this.status = !this.status;
}
Haroldo Gondim
  • 7,369
  • 9
  • 43
  • 61
Bilal Ahmad
  • 513
  • 4
  • 9
1

So normally you would create a backing variable in the class and toggle it on click and tie a class binding to the variable. Something like:

@Component(
    selector:'foo',
    template:`<a (click)="onClick()"
                         [class.selected]="wasClicked">Link</a>
    `)
export class MyComponent {
    wasClicked = false;

    onClick() {
        this.wasClicked= !this.wasClicked;
    }
}
Hammad Ahmad
  • 111
  • 6
1

You can try this.

Html.

<button *ngFor="let color of colors; let index=index" class="example1" 
        (click)="selectColor(index)" [class.choose__color]="viewMode == index">
    <mat-icon>fiber_manual_record</mat-icon>
</button>

css.

.example1:hover {
    border-bottom: 2px solid black;
}

.choose__color {
     border-bottom: 2px solid black;
}

ts.

selectColor(index: any) {
    this.viewMode = index;
}
Josef
  • 2,124
  • 1
  • 20
  • 21