83

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
  • 5,293
  • 16
  • 54
  • 99

9 Answers9

159

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;       
}
upe
  • 1,862
  • 1
  • 19
  • 33
Mani S
  • 2,501
  • 1
  • 12
  • 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
76

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,917
  • 22
  • 40
  • 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
42

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 ;)

upe
  • 1,862
  • 1
  • 19
  • 33
neox5
  • 1,621
  • 13
  • 16
15

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.

upe
  • 1,862
  • 1
  • 19
  • 33
Saurabh Tiwari
  • 4,632
  • 9
  • 42
  • 82
11

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
  • 4,499
  • 4
  • 35
  • 50
3

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
  • 49
  • 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,725
  • 9
  • 43
  • 62
Bilal Ahmad
  • 781
  • 8
  • 10
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
  • 184
  • 1
  • 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,869
  • 2
  • 22
  • 23