Wednesday, 12 April 2017

Conditionally add class to an element on click - angular 2+

Angular 2+ngClassConditionally add class

Here I am going to discuss about adding a class to an active element. For example if we click on a link or dynamic menu we need to highlight that with a color. In this article we will be discussing the same in different scenarios.

  1. Add class to an element on click and remove on click of other item and highlight the current one. (With js and With out js)
  2. Add class to an element on click and remove if we click again on the same.(With js and With out js)

Let us check one by one.

1. Add class to an element on click and remove on click of other item and highlight the current one.


Let us check how we can achieve this by using very less code.

Html


<div>
  <ul>
 <li *ngFor="let n of list" (click)="select(n)" [ngClass]="{active: isActive(n)}">
  <a>{{n}}</a>
 </li>
  </ul>
</div>

Component


export class App {
  list:any;
  selected :any;
  constructor() {
    this.list = [
       'Read about Angular',
       'Read about knockout',
       'Read about backbone',
       'Read about jquery',
       'Read about javascript'
    ]; 
  }
  select(item) {
      this.selected = item; 
  };
  isActive(item) {
      return this.selected === item;
  };

}

Here I have used *ngFor to loop and angular click method for click event.

Dont forget to add below css


.active a{color:red;}

Add class to an element on click, by only using html code

The above one you can achieve with out using any js code it self. It required some changes in the html. Please see below code for that.


<div>
  <ul>
    <li *ngFor="let n of list" [class.active]="clicked === n" 
         (click)="clicked = n">
       <a>{{n}}</a>
    </li>
  </ul>
</div>

2. Add class to an element on click and remove if we click again on the same.


Now let us check another scenario. We will add class and remove if user clicks again on the same item. For achieving this functionality you can follow above same code except one small change in one method. See below updated method.


select(item) {
   this.selected = (this.selected === item ? null : item); 
};

Using this approach you can easily find out user is clicking on same item again or not and you can write you're on logic also in this scenario. See the below code for more info.


 select(item) {
  if(item === this.selected)
   {
      this.selected = null;
      //your logic
    }else
    {
      this.selected = item;
      //your logic
     }
 };

Add class to an element on click and remove on same click, by only using html code

The above one you can achieve with out using any js code it self. It required some changes in the html. Please see below code for that.


<div>      
 <ul>
   <li *ngFor="let n of list" [class.active]="clicked === n" 
       (click)="clicked = (clicked === n ? null :n)">
     <a>{{n}}</a>
   </li>
  </ul>
</div>

I didn't add all examples in the plunker, but you can always edit and play on that.

I have explained about 5 different ways for adding a class dynamically using Angular, please check those here:- 5 different ways for conditionally adding class - Angular.

Here we have discussed about adding a class to an item on click.

Angular 2+ngClassConditionally add class

Related Info

1. Date filtering and formatting using pipe in Angular 2

2. Simple search using pipe in angular 2

3. Angular 2 toggle button | Angular 2 collapsible panel

8 comments :

  1. Hi,
    This is amazing. I applied this to my thumbnails in Angular 2, so whenever clicked the background colour changes.
    My problem is that the backgroud changes only while I am pressing on the mouse. As soon as I release the mouse, the thumbnail is not active anymore. So, do you have any suggestions for that?

    ReplyDelete
    Replies
    1. I am not sure what is happening in your case. Add important to your css and try once. Difficult to judge with out seeing the code.

      Delete
  2. Hi ABC.com

    saw ur post and implemented ur code in my project:
    Add class to an element on click, by only using html code on tr like somewhat like this
    .
    .
    .
    .
    .
    --tr-- *ngFor="let n of list" [class.active]="clicked === n" (click)="clicked = n"
    --td--Some data....--/td--
    --td--Some data....--/td--
    --td--Modal popup button--/td--
    --td--Some data....--/td--
    --tr--

    Now when i click on modal popup active class added to the parent tr!
    How to prevent this from happening ?
    DdotRANOLIA92@GMAILdotCOM

    ReplyDelete
    Replies
    1. Try to add e.stopPropagation(); on Model popup button click.

      Delete
  3. Thank you, that's what I want, it's works for me, I have a question: How can I set the default selected for this example,
    AngularFireStore, I did try that but not working:

    // .ts File

    currency:any;
    currencySelected :any;

    constructor(private currencyService: CurrencyService) {
    currencyService.currencies.subscribe((currencie) => {
    this.currencySelected = currencie[0]; // I got first object successfully, but not set
    });
    }


    setCurrencyActive( currency ) {
    this.currencySelected = currency;
    }

    isCurrencyActive( currency ) {
    return this.currencySelected === currency;
    }

    // .html File

    --li *ngFor="let currency of currencyService.currencies | async" [ngClass]="{'active': isCurrencyActive(currency)}" (click)="setCurrencyActive(currency)"--
    {{ currency.name }}
    --/li--

    ReplyDelete
    Replies
    1. One of the easiest way to do this is that, just invoke the method after getting the result. For example ,in my above example case..
      Call this method after getting result
      this.select(this.list[0]);

      In your case, might be something like this
      this.setCurrencyActive(this.currencySelected);

      Delete
  4. This is very good exampler but if 2 names are same both are clicked, if at arrays you have names, id and other things the best thing is selected to be like this.selected = item.id or something like this. But this code helped me so much.
    Best Regards
    You are very very good

    ReplyDelete