简体   繁体   中英

Angular mat-slider animate from 100 to 0 when opening in the dialog

I have the angular component that is opened in the dialog. My mat-slide is defined as below:

<mat-slider min="0" max="100" [value]="progressBarValue" (change)="changeProgress($event)"></mat-slider>

But when the dialog is opened, the mat slider progress value is animated from 100 to 0, Even though i already set the progressBarValue=0 in the constructor.

I don't know why. My other components showing the same in the template doesn't have such kind of issue.

Does anybody met this kind of behavior? 在此处输入图像描述

I want this to be at 0 without animation from 100 to 0. Please see to the end of the gif.

I minimize the source code as below, still has the same issue

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-insert',
  templateUrl: './insert.html',
  styleUrls: ['./insert.scss']
})
export class InsertComponent implements OnInit {

    progressBarValue: number;

    constructor() {
        this.progressBarValue = 0;
    }

    ngOnInit() {
    }

}

In the component html

<mat-slider min="0" max="100" [value]="progressBarValue"></mat-slider>

In another component to launch the above component in the dialog

        const dialog = {
           currentTime: 0
        };
        const dialogRef = this.dialog.open(InsertComponent, {
            panelClass: 'app-dialog',
            data: dialog,
            autoFocus: false
        });
        dialogRef.afterClosed().subscribe((currentTime) => {
        });

If someone knows why this happens, please let me know. Thanks a lot.

The attribute directive ngStyle in combination with the assigned functions, which are used on several different elements of the mat-slider, trigger CSS transformations every time the value of the slider changes:

<!-- slider html template excerpt -->
<div class="mat-slider-wrapper" #sliderWrapper>
  <div class="mat-slider-track-wrapper">
    <div class="mat-slider-track-background" [ngStyle]="_trackBackgroundStyles"></div>
    <div class="mat-slider-track-fill" [ngStyle]="_trackFillStyles"></div>
  </div>
  ...
</div>
// slider component excerpt
get _trackBackgroundStyles(): { [key: string]: string } {
    const axis = this.vertical ? 'Y' : 'X';
    const scale = this.vertical ? `1, ${1 - this.percent}, 1` : `${1 - this.percent}, 1, 1`;
    const sign = this._shouldInvertMouseCoords() ? '-' : '';

    return {
      // scale3d avoids some rendering issues in Chrome. See #12071.
      transform: `translate${axis}(${sign}${this._thumbGap}px) scale3d(${scale})`
    };
  }
...

(see full source: MatSlider html source and MatSlider ts source ).

Due to the way how a component is instantiated and injected into the dialog, a transformation is triggered here during the initialization process. So in order to achieve your desired behaviour the CSS animations need to be (temporarily) disabled.

A (probably very hacky but working) solution is to disable the animation by adding a class to the mat-slider which will remove the transition and remove that class after the initialization completed:

<!-- insert.component.html -->
<mat-slider [ngClass]="{'disableAnimation':isAnimationDisabled}" min="0" max="100" [(ngModel)]="progressBarValue" (change)="changeProgress($event)"></mat-slider>
/* insert.component.css */
::ng-deep .disableAnimation *{
 transition: none !important;
}
// insert.component.ts
...

@Component({
  ...
})
export class InsertComponent implements AfterViewInit {
  ...  
  isAnimationDisabled: boolean = true;

  ...

  ngAfterViewInit() {
    setTimeout(() => {
      this.isAnimationDisabled = false;
    })
  }
}

Since the initialization process is completed very very quickly in this example you need to use setTimeout, otherwise you'll get an ExpressionChangedAfterItHasBeenCheckedError. To prevent that you could also change the ChangeDetectionStrategy to OnPush and manually trigger the change detection once the initialization is finished.

I've create a Stackblitz for you to play with.

To specifically target just the slide animation on the mat-sliders on initialization you can just override the transition for that piece of css.

.mat-slider {
     .mat-slider-thumb-container {
         transition: none;
     }
}

Placed in your component or global stylesheet.

using EventEmitter we can solve this issue

HTML File:

  <div class="price-slider-wrapper" lines="none">
       <ng5-slider color="primary" [(value)]="minPrice" [(highValue)]="maxPrice" 
                      (userChange)="priceSliderChange($event)"
             [options]="premoptions" (click)="$event.stopPropagation();"  [manualRefresh]="manualRefresh">
      </ng5-slider>
 </div> 

TS file:

  public manualRefresh = new EventEmitter<void>();
 priceMenuOpen:boolean = false;

  openPriceSlider(){
        this.priceMenuOpen = true;
        setTimeout(() => {
            this.manualRefresh.emit();
        }, 200);
    }

on menu click event called openPriceSlider() function:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM