Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 - Change icon on click

I have a materialize collapsible list in my angular2 application. What I want to do, is change the icon of the list item when someone clicks on it. So far I attached a click event onto the list. When I print this out to the console, I see the element reference. So I'm able to look down the child nodes and find the li element that has the active class attached to it. My thinking is that once I find the active element I can just change the child node's icon to the new one. This way I don't change all the icons. However, when I try to set the icon to the new icon, I get TypeError: 0 is read-only. Does anyone know how to do this via angular 2?

Plunker
https://plnkr.co/edit/jQWf7uIRZIwr4fhyFT03?p=preview

List

  <ul class="collapsible" data-collapsible="accordion">
    <li>
      <div class="collapsible-header"><i class="material-icons">filter_drama</i>First</div>
      <div class="collapsible-body"><span>Lorem ipsum dolor sit amet.</span></div>
    </li>
    <li>
      <div class="collapsible-header"><i class="material-icons">place</i>Second</div>
      <div class="collapsible-body"><span>Lorem ipsum dolor sit amet.</span></div>
    </li>
    <li>
      <div class="collapsible-header"><i class="material-icons">whatshot</i>Third</div>
      <div class="collapsible-body"><span>Lorem ipsum dolor sit amet.</span></div>
    </li>
  </ul>

Desired Behavior: Basically I'm trying to make a drop down tree using materlize collapsible list. So you click on an item it changes its icon from a plus sign to a minus sign to simulate that you are expanding and contracting the item.

Picture Example Link

like image 535
AJ_ Avatar asked Aug 23 '17 02:08

AJ_


1 Answers

Angular only solution (no jQuery needed)

You can simply toggle between two icons using a variable that you change on click:

<div class="collapsible-header" (click)="showFirst=!showFirst"><i class="material-icons" *ngIf="showFirst">filter_drama</i><i class="material-icons" *ngIf="!showFirst">place</i>First Section</div>

If you want only to hide the icon, you do it the same way with only one icon:

<div class="collapsible-header" (click)="showSecond=!showSecond"><i class="material-icons" *ngIf="!showSecond">place</i>Second Section</div>

I forked your plunker and edited the changes here

PS: On your plunker you were loading material icons from a http url, making chrome to refuse to load the resource. Change the url to https and it will work.

Edit

@Judson Terrell - for me, Angular only solution looks cleaner

Angular only

<div class="collapsible-header" (click)="!show=show"><i class="material-icons" *ngIf="show">filter_drama</i>First</div>

Angular + jQuery

html

<div class="collapsible-header" id="clickedId"><i class="material-icons" id="someId">filter_drama</i>First</div>

js

$( "#clickedId" ).click(function() {
  $("#someId").toggleClass('someIconClass');
});

+ jQuery lib- and the presumable performance problems it induces

Edit2 - after clearing the question

What you want is achievable using CSS only:

html:

<div class="collapsible-header"><i class="material-icons more">expand_more</i><i class="material-icons less">expand_less</i>First Section</div>

css:

.collapsible-header.active i.more{
display:none;
}

.collapsible-header.active i.less{
display:block;
}

.collapsible-header i.less{
display:none;
}

Updated plunker here

Credit for idea to this answer

like image 166
BogdanC Avatar answered Nov 05 '22 03:11

BogdanC