Changing Rotation of Mat Expansion Indicator

Changing Rotation of Mat Expansion Indicator

mat expansion indicator's rotation is handled by this animation. as it can be seen there it is straightforward rotate(180deg) (180deg clockwise). and indicator initially has rotate(45deg) which show downward icon by default when panel is closed and upward icon when panel is open with clockwise animation.

when you apply rotation with;

.mat-expansion-indicator::after {
transform: rotate(225deg) !important;
}

icon is rotated upwards initially when panel is closed, when clicked it is rotated by 180deg clockwise. at this point you cannot show downwards icon when closed and upwards when open because of rotate(225deg) if you change that you loose inward turning because animation starts clockwise, but we need exactly the opposite.

eventually it is not possible to have counter-clockwise rotation without overriding default animation. Unfortunately, Angular Material doesn't have any mechanism to override default animations, as seen here .

so my solution is to completely disable default animations on mat-expansion-panel-header and implement a custom directive that imitates this animation but counter-clockwise.

first disable default animation on mat-expansion-panel-header;

<mat-expansion-panel-header [@.disabled]="true">

then create new animations in styles.css with same timing and behavior as default animation.

@keyframes inwards-open {
0% { transform: rotate(0deg); }
100% { transform: rotate(-135deg); }
}

@keyframes inwards-close {
0% { transform: rotate(-135deg); }
100% { transform: rotate(0deg); }
}

.openAnimate {
animation: inwards-open 225ms cubic-bezier(0.4,0.0,0.2,1) !important;
}

.closeAnimate {
animation: inwards-close 225ms cubic-bezier(0.4,0.0,0.2,1) !important;
}

and implement a custom directive that handles animation status based on panel open/close events

import { Directive, ElementRef, HostListener, AfterViewInit, OnDestroy } from '@angular/core';
import { fromEvent, Subscription } from 'rxjs';

@Directive({
selector: '[appCustomMatExpansionToggle]'
})
export class CustomMatExpansionToggleDirective implements AfterViewInit, OnDestroy {
private elem: HTMLSpanElement;
private uns: Subscription;
constructor(private elRef: ElementRef) {}

ngAfterViewInit() {
this.elem = this.elRef.nativeElement.querySelector(".mat-expansion-indicator");

this.uns = fromEvent(this.elem, 'animationend').subscribe(() => {
this.elem.classList.remove("openAnimate");
this.elem.classList.remove("closeAnimate");
});
}

@HostListener("opened")
onOpen() {
this.elem.classList.add("openAnimate");
}

@HostListener("closed")
onClose() {
this.elem.classList.add("closeAnimate");
}

ngOnDestroy() {
this.uns.unsubscribe();
}
}

and finally apply the custom directive to mat-expansion-panel

<mat-expansion-panel appCustomMatExpansionToggle>

here is a working demo https://stackblitz.com/edit/indicatorrotation-mp73uh

Mat Expansion Panel show indicator on disabled and change direction of animation

To show the chevron or indicator even when the panel is disabled try as below:

HTML

<mat-expansion-panel [disabled]="boolCondition">
<mat-expansion-panel-header>
<mat-panel-title>
Personal data
// you have to add the below span tag in every expansion panel with a condition
<span *ngIf="boolCondition" class="mat-expansion-indicator"></span>
</mat-panel-title>
</mat-expansion-panel-header>

CSS

.mat-expansion-indicator::after {
transform: rotate(225deg) !important;
}

// for the mat-expansion indicator to displayed when it is disabled
.mat-expansion-indicator {
position: absolute;
right: 55px;
}

stackblitz working demo

Border css changes faster than transform rotate

Update :

Well I hope this helps... Not actually a solution to your problem... Just another method to get the same visual effect... : https://stackblitz.com/edit/angular-material-4pcnph?file=app/app.component.css

Original Answer:

(Answering your tldr question)

When the mat-expansion-panel is expanded it has a class mat-expanded

So you can use that to write your css something like :

.mat-expansion-indicator::after{ /* when its 0deg */
color: blue; /* whatever */
}

.mat-expanded .mat-expansion-indicator::after{ /* when its 180deg */
color: red; /* whatever */
}

Demo : https://stackblitz.com/edit/angular-tcy7fh?file=styles.css

Change width and height of mat-expansion indicator

Looks like your css is not being used. I know it's deprecated, but have you tryed using ::ng-deep?

::ng-deep .mat-expansion-indicator::after {
border-style: solid;
border-width: 0 5px 5px 0 !important;
content: '' !important;
padding: 5px;
}

How to change toggle icon of mat-expansion-panel?

As stated on the Angular Material Expansion Panel documentation, we can customise the stylings of the mat-extension-panel-header, which will in turn allow you to customise the icons.

First and foremost, you hide the original icon by setting the hideToggle attribute to true. In addition, we assign the event bindings (opened) and (closed) to the panelOpenState property. You may check out the other properties of mat-expansion-panel over here.

<mat-expansion-panel (opened)="panelOpenState = true" (closed)="panelOpenState = false"hideToggle="true">

Next, on your mat-panel-description, you include the custom icons required. The icons shown will be dependent on the state of the panel. For this example, we are using the icons from Material Icons.

<mat-panel-description>
<mat-icon *ngIf="!panelOpenState">add</mat-icon>
<mat-icon *ngIf="panelOpenState">remove</mat-icon>
</mat-panel-description>

I have edited the original sample from the Angular documentation, such that it is using the custom + and minus icons to denote the expanded/collapsed state of the mat-extension-panel. You may access the demo over here.

How to position the Angular Material expansion panel arrow icon on the left-hand side

first you need to import angular material icon and expansion panel module in app.module.ts file,

import {MatExpansionModule,MatIconModule} from '@angular/material';
...
@NgModule({
...
imports: [
MatExpansionModule,
MatIconModule
]
...
})
export class AppModule { }

Add this code in your HTML file,

    <mat-expansion-panel expanded='true' hideToggle="true" (click)="click()">
<mat-expansion-panel-header [ngClass]="tickets-container-header">
<mat-panel-title>
<mat-icon>{{icon ? 'keyboard_arrow_down' : 'keyboard_arrow_up' }}</mat-icon>
<div class="col-md-9">
{{header}}
</div>
</mat-panel-title>

</mat-expansion-panel-header>
</mat-expansion-panel>

Add this code in your component file,

icon: boolean = false;

click(){
this.icon = !this.icon;
}

Thanks,

Change color of contents in Mat Expansion on hover and focus

To achieve expected result, use below option
mat-expansion-indicator is not direct child of panel, so onhover of panel, change color of indicator

.mat-expansion-panel:hover  .mat-expansion-indicator::after,
.mat-expansion-panel:focus .mat-expansion-indicator::after{
color: yellow;
}

codesandbox for reference - https://codesandbox.io/s/angular-hh3oz

Change arrow style for default expansion panel arrow

Yes it is possible. Give your expansion panel a reference id e.g. example and set the hideToggle property as true.

In the <md-panel-description>, you can place your icons and use the expanded property of the panel to show or hide the relevant icons.

  <md-expansion-panel  class="custom-header" hideToggle="true" #example>
<md-expansion-panel-header>
<md-panel-title>
Personal data
</md-panel-title>
<md-panel-description>
Type your name and age
<md-icon *ngIf="!example.expanded">play_arrow</md-icon>
<md-icon *ngIf="example.expanded">arrow_drop_down</md-icon>
</md-panel-description>
</md-expansion-panel-header>

<md-form-field>
<input mdInput placeholder="First name">
</md-form-field>

<md-form-field>
<input mdInput placeholder="Age">
</md-form-field>
</md-expansion-panel>

To provide space between the icon and panel description, add the following classes in your component.css:

.custom-header .mat-expansion-panel-header-title, 
.custom-header .mat-expansion-panel-header-description {
flex-basis: 0;
}

.custom-header .mat-expansion-panel-header-description {
justify-content: space-between;
align-items: center;
}

I have used material icons. You can place your custom icons if you want. Here is a link to stackblitz demo.



Related Topics



Leave a reply



Submit