24

I need to show / hide part of component. Here is Angular2 example.

<li *ngFor=" #item of items " >
  <a href="#" (onclick)="hideme = !hideme">Click</a>
  <div [hidden]="hideme">Hide</div>
</li>

Suppose we have only 2 items. Problem here that it works on both items. So it hides and shows div part in both components. It could be perfect if we could have something like this:

<li *ngFor=" #item of items " >
   <a href="#" (onclick)="this.hideme = !this.hideme">Click</a>
   <div [hidden]="this.hideme">Hide</div>
</li>

So is there some simple way to solve this problem ?

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
YakovlevRoman
  • 3,362
  • 3
  • 19
  • 19
  • https://stackoverflow.com/questions/42017246/angular2-toggle-icons-inside-ngfor Please refer the above link for clear answer – sudhakar Sep 21 '17 at 05:42

6 Answers6

37

You're hideme variable is global. Perhaps you could attach it to the current item:

<li *ngFor=" #item of items " >
  <a href="#" (onclick)="item.hideme = !item.hideme">Click</a>
  <div [hidden]="item.hideme">Hide</div>
</li>

Otherwise you need to use a dedicated object object from your component. Here is a sample:

<li *ngFor="let item of items " >
  <a href="#" (onclick)="hideme[item.id] = !hideme[item.id]">Click</a>
  <div [hidden]="hideme[item.id]">Hide</div>
</li>

Don't forget to initialize the hideme object this way in your component:

hideme:<any> = {};

Edit

If you want to make this work like tabs, you need a bit more work ;-)

<li *ngFor="let item of items " >
  <a href="#" (onclick)="onClick(item)">Click</a>
  <div [hidden]="hideme[item.id]">Hide</div>
</li>

And to display the clicked element and hide others:

onClick(item) {
  Object.keys(this.hideme).forEach(h => {
    this.hideme[h] = false;
  });
  this.hideme[item.id] = true;
}
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • well it toggles elements but doesn't work like tabs, open one and close another, but any way it's almost the answer ) – YakovlevRoman Apr 28 '16 at 20:02
  • I added some code to implement the tab-like behavior ;-) Feel free to tell if it suits your needs ;-) – Thierry Templier Apr 28 '16 at 21:29
  • @ThierryTemplier Is there is live implementation of this hide and show I have no clue about items in the answers what it contains and how we id works and how It Identify each element to hide sperately – Malik Kashmiri Oct 14 '16 at 20:29
  • 1
    @ThierryTemplier how to hide items for the first time? when page loads? – Pratap A.K Dec 12 '16 at 06:39
  • @PratapA.K - Just change this line `
    Hide
    ` to this line `
    Hide
    `. Notice the `!` before `hideme..` in the second line
    – xaisoft Feb 01 '18 at 15:51
14

is work for me :

in your compoment decler about hideme as array

hideme=[]

and in the ngFor do that:

<li *ngFor="item of items;let i = index " >
   <a (click)="hideme[i] = !hideme[i]">show/hide</a>
   <div [hidden]="hideme[i]">The content will show/hide</div>
</li>
yanai edri
  • 359
  • 2
  • 4
4

In component class, declare hideme variable (typescript):

export class MyPage{
   hideme = {};
   constructor(){
       this.hideme = {}; // init is required
   }
   ...

Show/hide control in template:

<li *ngFor="item of items " >
   <a (click)="hideme[item.id] = !hideme[item.id]">show/hide</a>
   <div [hidden]="!hideme[item.id]">The content will show/hide</div>
</li>

Notes: hideme not required init because hideme[item.id] is undefined thus !hideme[item.id] will true.

nguyên
  • 5,156
  • 5
  • 43
  • 45
3

Here's an example that shows a plus sign when the parent item is collapsed and switches to a minus sign when it's expanded and shows a list of items that belong to the clicked category. (In your case, this would be the div that contains the things you want to show and hide instead of a list.)

I've achieved this using the details and summary elements instead of the accordion. These elements are purpose built for this use case.

Using the problem that was presented in this thread: angular2 toggle icons inside ngFor

Here are screenshots of what the collapsed and expanded category looks like:

Collapsed category with plus sign

Expanded category with minus sign

This is the template:

<ul *ngIf="categoryList && categoryList.length > 0">
        <li *ngFor="let category of categoryList">
            <details>
                <summary>
                    <i class="fa fa-lg expand-icon"></i>
                    <span>{{ category.name }}</span>
                </summary>
                <ul>
                    <li *ngFor="let item of category.yourItemListUnderCategory">{{ item }}</li>
                </ul>
            </details>
        </li>
    </ul>

I'm using Font Awesome for the plus and minus icons and here's how to toggle them. In your css, add the following styles:

(I'm referencing the icon with the class I assigned it but you can also do details summary i:before and details[open] summary i:before)

details summary .expand-icon:before {
    content: "\f055";
}
details[open] summary .expand-icon:before {
    content: "\f056";
}

Note: I'm using a Bootstrap theme for the screenshots but have stripped the class names on the elements to not clutter the answer.

Community
  • 1
  • 1
muzurB
  • 317
  • 2
  • 10
2

In HTML: (click)="onClick($event)"

Inside de function onClick, you can catch the event and use it like a jquery object, like this:

onClick(event){
   $(event.target).siblings('div').toggle(500);
}

In this example, I search for the sibling of my target object, you could do that with any object you need.

vrecalde
  • 21
  • 3
0

Add HTML ngFor by passing the values to the function.

<ul *ngFor="let ent of entities;let i = index">
  <li>
    <div (click)="showEntity(ent)">
      <h5 class="h5">
        {{ent.values}}
      </h5>
      <p [hidden]="!hideme["ent.id]">
        <span class="play-icon"></span>
        {{ent.name}}
      </p>
    </div>
  </li>
</ul>

declare variable.

 hideme = {};
 entities = [
    { id: 1, values: "Animal", name: "Tiger" },
    { id: 2, values: "Bird", name: "Sparrow" },
    { id: 3, values: "River", name: "Nile" }
  ];

initiate it in the constructor and onInit.

  constructor() {
    this.hideme = {};
  }

  ngOnInit(): void {
    this.entities.forEach(e => {
      this.hideme[e.id] = false;
    });
  }

set all values to false.

then onclick .

 showEntity(item) {
   Object.keys(this.hideme).forEach(h => {
     this.hideme[h] = false;
   });
   this.hideme[item.id] = true;
 }

change flag of that perticular id to true and rest of them will be false

Check stackblitz here!