2

data

test = [
    {
      "test1": {
            "qq": ["qq", "ww", "aa", "bb"],
          },
    },
    {
      "test1": {
            "qq": ["11", "22", "33", "44"],
          },
    }
];

code

<ng-container *ngFor="let list of test">

  <div class="a" (click)="clickEvent(list)" [ngClass]="list.status ? 'blue' : ''">
    {{list.test1.qq[0]}}
    </div>

  <div class="a" (click)="clickEvent(list)" [ngClass]="list.status ? 'blue' : ''">
    {{list.test1.qq[1]}}
    </div>
</ng-container>

ts

status: boolean = false;
clickEvent(list){
    list.status = !list.status;       
}

https://stackblitz.com/edit/angular-skdlf2?file=src%2Fapp%2Fapp.component.ts

enter image description here

Now I click 'qq', 'ww' will also toggle class

But I just want to toggle a class on single div.

Click 'qq', Only 'qq' toggle class

How to do it?

4
  • 1
    This is a terrible example to learn. But to explain it to you, you're iterating over a list, and binding the status to that list. Since you display two items from the same iteration, clicking on one result in the other one having the same result, because of the same condition. If you add a third list item, then you will have the same issue on 3 items. Consider binding the status to the final items, not the list itself. Commented Mar 12, 2019 at 13:08
  • What is the logic behind toggle? Or just next div? Commented Mar 12, 2019 at 13:08
  • you are looping the ng-container that contains two div elements. So technically you are clicking on the ng-container and list item you are clicking on is the same for each div in each iteration, so this is the very reason this is happening. try using only one div in ng-container. Commented Mar 12, 2019 at 13:13
  • Unrelated, but you should use [class.blue]="list.status" instead of [ngClass]="list.status ? 'blue' : '' ". It's more readable and you can toggle multiple independant css classes that way. Commented Mar 12, 2019 at 13:18

3 Answers 3

2

The *ngFor do not create multiple instances, you have actually only one instance. So if you change the status all your divs will change.

The solution is to create a childComponent, the *ngFor will iterate and create as many component instance as items.

With that, every component (item) will have it own status.

I hope this will help !

Sign up to request clarification or add additional context in comments.

Comments

0

Depending on the structure of your array, you might need to pass the targeted item to the click handler. Which in your case list.test1.qq[1] or list.test1.qq[0].

Then you might need to separately tell your component which item is clicked, because the targeted item in your case is a string.

In my working solution, I've just defined a string called clicked which will memorize and toggle the targeted item and passed the targeted item to the click handler.

My Working Soulution on stackblitz

5 Comments

Thanks. But have a little bug. If have the same string, it will be wrong.
Could you please be more spacific and give an example about that little bug?
test = [ { "test1": { "qq": ["qq", "ww", "aa", "bb"], }, }, { "test1": { "qq": ["11", "qq", "33", "44"], }, } ]
like that.If have two "qq" click one both "qq" will toggle
Yea, in this case you might need to use the items index to avoid this situation. Here i have the working soultion: stackblitz.com/edit/angular-jqxmqj
0

<div class= "container">
<li *ngFor="let list of test"></li>

  <div class="a" (click)="clickEvent(list)" [ngClass]="list.status ? 'blue' : ''">
    {{list.test1.qq[0]}}
    </div>

  <div class="a" (click)="clickEvent(list)" [ngClass]="list.status ? 'blue' : ''">
    {{list.test1.qq[1]}}
    </div>
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.